Initial commit
This commit is contained in:
commit
f9f65dc84d
23 files changed
+5074
No files matched your search
@@ -0,0 +1,355 @@
|
||||
<?php if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly
|
||||
|
||||
/**
|
||||
* Simply Static URL fetcher class
|
||||
*
|
||||
* @package Simply_Static
|
||||
*/
|
||||
class Simply_Static_Archive_Creator {
|
||||
|
||||
/**
|
||||
* The path to the archive directory
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $archive_dir;
|
||||
|
||||
/**
|
||||
* Export log (list of processed urls)
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $export_log = array();
|
||||
|
||||
/**
|
||||
* The slug (id) used for the plugin
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $slug;
|
||||
|
||||
/**
|
||||
* The protocol used for the destination URL
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $destination_scheme;
|
||||
|
||||
/**
|
||||
* The host for the destination URL
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $destination_host;
|
||||
|
||||
/**
|
||||
* The directory where static files should be saved
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $temp_files_dir;
|
||||
|
||||
/**
|
||||
* Additional urls to add to the archive
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $additional_urls;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param string $url URI resource
|
||||
*/
|
||||
public function __construct( $slug, $destination_scheme, $destination_host, $temp_files_dir, $additional_urls ) {
|
||||
$this->slug = $slug;
|
||||
$this->destination_scheme = $destination_scheme;
|
||||
$this->destination_host = $destination_host;
|
||||
$this->temp_files_dir = $temp_files_dir;
|
||||
$this->additional_urls = $additional_urls;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the list of URLs in the archive
|
||||
*
|
||||
* @param array $export_log URLs that were successfully added to the archive
|
||||
*/
|
||||
public function get_export_log() {
|
||||
return $this->export_log;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a static version of the site
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function create_archive() {
|
||||
global $blog_id;
|
||||
// TODO: Do ajax calls instead of just running forever and ever
|
||||
set_time_limit(0);
|
||||
|
||||
// Create archive directory
|
||||
$current_user = wp_get_current_user();
|
||||
$archive_name = join( '-', array( $this->slug, $blog_id, time(), $current_user->user_login ) );
|
||||
$this->archive_dir = trailingslashit( $this->temp_files_dir . $archive_name );
|
||||
|
||||
if ( ! file_exists( $this->archive_dir ) ) {
|
||||
wp_mkdir_p( $this->archive_dir );
|
||||
}
|
||||
|
||||
// Add URLs to queue
|
||||
$origin_url = home_url();
|
||||
$destination_url = $this->destination_scheme . '://' . $this->destination_host;
|
||||
$urls_queue = array_unique( array_merge(
|
||||
array( trailingslashit( $origin_url ) ),
|
||||
// using preg_split to intelligently break at newlines
|
||||
// see: http://stackoverflow.com/questions/1483497/how-to-put-string-in-array-split-by-new-line
|
||||
preg_split( "/\r\n|\n|\r/", $this->additional_urls )
|
||||
) );
|
||||
|
||||
while ( count( $urls_queue ) ) {
|
||||
$current_url = array_shift( $urls_queue );
|
||||
|
||||
$response = Simply_Static_Url_Fetcher::fetch( $current_url );
|
||||
|
||||
// If we get a WP_Error then somehow our request failed (e.g. space in URL)
|
||||
// TODO: Keep a queue of failed urls too
|
||||
if ( is_wp_error( $response ) ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$url_parts = parse_url( $response->url );
|
||||
$path = $url_parts['path'];
|
||||
$is_html = $response->is_html();
|
||||
|
||||
// If we get a 30x redirect...
|
||||
if ( in_array( $response->code, array( 301, 302, 303, 307 ) ) ) {
|
||||
|
||||
$redirect_url = $response->get_redirect_url();
|
||||
|
||||
// WP likes to 301 redirect `/path` to `/path/` -- we want to
|
||||
// check for this and just add the trailing slashed version
|
||||
if ( $redirect_url === trailingslashit( $current_url ) ) {
|
||||
|
||||
$urls_queue = $this->add_url_to_queue( $urls_queue, $redirect_url );
|
||||
|
||||
} else {
|
||||
|
||||
/// convert our potentially relative URL to an absolute URL
|
||||
$redirect_url = sist_relative_to_absolute_url( $redirect_url, $current_url );
|
||||
|
||||
if ( $redirect_url ) {
|
||||
|
||||
// check if this is a local URL
|
||||
if ( sist_is_local_url( $redirect_url ) ) {
|
||||
|
||||
// add the redirected page to the queue
|
||||
$urls_queue = $this->add_url_to_queue( $urls_queue, $redirect_url );
|
||||
// and update the URL
|
||||
$redirect_url = str_replace( $origin_url, $destination_url, $redirect_url );
|
||||
|
||||
}
|
||||
|
||||
$view = new Simply_Static_View();
|
||||
|
||||
$content = $view->set_template( 'redirect' )
|
||||
->assign( 'redirect_url', $redirect_url )
|
||||
->render_to_string();
|
||||
|
||||
$this->save_url_to_file( $path, $content, $is_html );
|
||||
|
||||
$this->export_log[] = $current_url;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
// Not a 200 for the response code? Move on.
|
||||
// TODO: Keep a queue of failed urls too
|
||||
if ( $response->code != 200 ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$this->export_log[] = $current_url;
|
||||
|
||||
// Fetch all URLs from the page and add them to the queue...
|
||||
$urls = $response->extract_urls();
|
||||
foreach ( $urls as $url ) {
|
||||
$urls_queue = $this->add_url_to_queue( $urls_queue, $url );
|
||||
}
|
||||
|
||||
// Replace the origin URL with the destination URL
|
||||
$response->replace_url( $origin_url, $destination_url );
|
||||
|
||||
// Save the page to our archive
|
||||
$content = $response->body;
|
||||
$this->save_url_to_file( $path, $content, $is_html );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a URL to the processing queue if we haven't already processed it and
|
||||
* if it's not in the queue to be processed
|
||||
*
|
||||
* @param array $urls_queue Queue of URLs to be processed
|
||||
* @param string $url URL to add to the processing queue
|
||||
* @return array Queue of URLs to be processed
|
||||
*/
|
||||
private function add_url_to_queue( $urls_queue, $url ) {
|
||||
if ( ! in_array( $url, $this->export_log ) && ! in_array( $url, $urls_queue ) ) {
|
||||
$urls_queue[] = $url;
|
||||
}
|
||||
|
||||
return $urls_queue;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a ZIP file using the archive directory
|
||||
*
|
||||
* @return string|WP_Error $temporary_zip The path to the archive zip file
|
||||
*/
|
||||
public function create_zip() {
|
||||
$temporary_zip = untrailingslashit( $this->archive_dir ) . '.tmp';
|
||||
$zip_archive = new ZipArchive();
|
||||
|
||||
if ( $zip_archive->open( $temporary_zip, ZIPARCHIVE::CREATE ) !== true ) {
|
||||
return new WP_Error( 'create_zip_failed', __( 'Unable to create ZIP archive', $this->slug ) );
|
||||
}
|
||||
|
||||
$iterator = new RecursiveIteratorIterator( new RecursiveDirectoryIterator( $this->archive_dir ) );
|
||||
foreach ( $iterator as $file_name => $file_object ) {
|
||||
$base_name = basename( $file_name );
|
||||
|
||||
if ( $base_name != '.' && $base_name != '..' ) {
|
||||
if ( ! $zip_archive->addFile( realpath( $file_name ), str_replace( $this->archive_dir, '', $file_name ) ) ) {
|
||||
return new WP_Error( 'cannot_add_file_to_zip', sprintf( __( "Could not add file: %s", $this->slug ), $file_name ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$zip_archive->close();
|
||||
$zip_file = untrailingslashit( $this->archive_dir ) . '.zip';
|
||||
rename( $temporary_zip, $zip_file );
|
||||
|
||||
$archive_url = str_replace( plugin_dir_path( dirname( __FILE__ ) ), plugin_dir_url( dirname( __FILE__ ) ), $zip_file );
|
||||
|
||||
return $archive_url;
|
||||
}
|
||||
|
||||
/**
|
||||
* Publish to AWS S3 bucket
|
||||
*
|
||||
* @return boolean|WP_Error
|
||||
*/
|
||||
public function publish_to_s3( $bucket, $aws_access_key_id, $aws_secret_access_key, $aws_s3_region = 'us-east-1', $aws_s3_endpoint = 's3.amazonaws.com' ) {
|
||||
$directory_iterator = new RecursiveDirectoryIterator( $this->archive_dir, RecursiveDirectoryIterator::SKIP_DOTS );
|
||||
$recursive_iterator = new RecursiveIteratorIterator( $directory_iterator, RecursiveIteratorIterator::SELF_FIRST );
|
||||
|
||||
S3::$useExceptions = true;
|
||||
$useSSL = true;
|
||||
$endpoint = $aws_s3_endpoint;
|
||||
if ( preg_match( '#^https://#i', $endpoint ) ) {
|
||||
$useSSL = true;
|
||||
$endpoint = preg_replace( '#^https://#i', '', $endpoint );
|
||||
} elseif ( preg_match( '#^http://#i', $endpoint ) ) {
|
||||
$useSSL = false;
|
||||
$endpoint = preg_replace( '#^http://#i', '', $endpoint );
|
||||
}
|
||||
$endpoint = untrailingslashit( $endpoint );
|
||||
if ( empty( $endpoint ) ) {
|
||||
$endpoint = 's3.amazonaws.com';
|
||||
}
|
||||
|
||||
$s3 = new S3( $aws_access_key_id, $aws_secret_access_key, $useSSL, $endpoint, $aws_s3_region );
|
||||
S3::setRegion( $aws_s3_region );
|
||||
|
||||
foreach ( $recursive_iterator as $item ) {
|
||||
if (!$item->isDir()) {
|
||||
$path = $recursive_iterator->getSubPathName();
|
||||
try {
|
||||
$s3->putObject( S3::inputFile( $item->getRealPath() ), $bucket, $path, S3::ACL_PUBLIC_READ );
|
||||
} catch (any $err) {
|
||||
return new WP_Error( 'cannot_publish_to_s3', sprintf( __( "Could not publish file to S3: %s: %s", $this->slug, $err ), $path ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Copy static files to a local directory
|
||||
*
|
||||
* @return boolean|WP_Error
|
||||
*/
|
||||
public function copy_static_files( $local_dir ) {
|
||||
$directory_iterator = new RecursiveDirectoryIterator( $this->archive_dir, RecursiveDirectoryIterator::SKIP_DOTS );
|
||||
$recursive_iterator = new RecursiveIteratorIterator( $directory_iterator, RecursiveIteratorIterator::SELF_FIRST );
|
||||
|
||||
foreach ( $recursive_iterator as $item ) {
|
||||
$path = $local_dir . $recursive_iterator->getSubPathName();
|
||||
$success = $item->isDir() ? wp_mkdir_p( $path ) : copy( $item, $path );
|
||||
if ( ! $success ) {
|
||||
return new WP_Error( 'cannot_create_file_or_dir', sprintf( __( "Could not create file or directory: %s", $this->slug ), $path ) );
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete generated static files
|
||||
*
|
||||
* @param $archive_dir The archive directory path
|
||||
* @return boolean|WP_Error
|
||||
*/
|
||||
public function delete_static_files() {
|
||||
$directory_iterator = new RecursiveDirectoryIterator( $this->archive_dir, FilesystemIterator::SKIP_DOTS );
|
||||
$recursive_iterator = new RecursiveIteratorIterator( $directory_iterator, RecursiveIteratorIterator::CHILD_FIRST );
|
||||
|
||||
// recurse through the entire directory and delete all files / subdirectories
|
||||
foreach ( $recursive_iterator as $item ) {
|
||||
$success = $item->isDir() ? rmdir( $item ) : unlink( $item );
|
||||
if ( ! $success ) {
|
||||
return new WP_Error( 'cannot_delete_file_or_dir', sprintf( __( "Could not delete temporary file or directory: %s", $this->slug ), $item ) );
|
||||
}
|
||||
}
|
||||
|
||||
// must make sure to delete the original directory at the end
|
||||
$success = rmdir( $this->archive_dir );
|
||||
if ( ! $success ) {
|
||||
return new WP_Error( 'cannot_delete_file_or_dir', sprintf( __( "Could not delete temporary file or directory: %s", $this->slug ), $item ) );
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Save the contents of a page to a file in our archive directory
|
||||
*
|
||||
* @param string $path The relative path for the URL to save
|
||||
* @param string $content The contents of the page we want to save
|
||||
* @param boolean $is_html Is this an html page?
|
||||
* @return boolean $success Did we successfully save the file?
|
||||
*/
|
||||
protected function save_url_to_file( $path, $content, $is_html ) {
|
||||
$path_info = pathinfo( $path && $path != '/' ? $path : 'index.html' );
|
||||
|
||||
// Create file directory if it doesn't exist
|
||||
$file_dir = $this->archive_dir . ( $path_info['dirname'] ? $path_info['dirname'] : '' );
|
||||
if ( empty( $path_info['extension'] ) && $path_info['basename'] == $path_info['filename'] ) {
|
||||
$file_dir .= '/' . $path_info['basename'];
|
||||
$path_info['filename'] = 'index';
|
||||
}
|
||||
if ( ! file_exists( $file_dir ) ) {
|
||||
wp_mkdir_p( $file_dir );
|
||||
}
|
||||
|
||||
// Save file contents
|
||||
$file_extension = ( $is_html || ! isset( $path_info['extension'] ) ) ? 'html' : $path_info['extension'];
|
||||
$file_name = $file_dir . '/' . $path_info['filename'] . '.' . $file_extension;
|
||||
$success = file_put_contents( $file_name, $content );
|
||||
return $success;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,69 @@
|
||||
<?php if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly
|
||||
|
||||
/**
|
||||
* Simply Static options class
|
||||
*
|
||||
* @package Simply_Static
|
||||
*/
|
||||
class Simply_Static_Options {
|
||||
/**
|
||||
* Options array
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $options = array();
|
||||
|
||||
/**
|
||||
* Defines options record in the wp_options table
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $option_key = null;
|
||||
|
||||
/**
|
||||
* Performs initializion of the options structure
|
||||
*
|
||||
* @param string $option_key The options key name
|
||||
*/
|
||||
public function __construct( $option_key ) {
|
||||
$options = get_option( $option_key );
|
||||
|
||||
if ( false === $options ) {
|
||||
$options = array();
|
||||
}
|
||||
|
||||
$this->options = $options;
|
||||
$this->option_key = $option_key;
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the option identified by $name with the value provided in $value
|
||||
*
|
||||
* @param string $name The option name
|
||||
* @param mixed $value The option value
|
||||
* @return Simply_Static_Options
|
||||
*/
|
||||
public function set( $name, $value ) {
|
||||
$this->options[$name] = $value;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a value of the option identified by $name
|
||||
*
|
||||
* @param string $name The option name
|
||||
* @return mixed|null
|
||||
*/
|
||||
public function get( $name ) {
|
||||
return array_key_exists( $name, $this->options ) ? $this->options[$name] : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Saves the internal options data to the wp_options table using the stored $option_key value as the key
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public function save() {
|
||||
return update_option( $this->option_key, $this->options );
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,211 @@
|
||||
<?php if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly
|
||||
|
||||
/**
|
||||
* Simply Static URL extractor class
|
||||
*
|
||||
* @package Simply_Static
|
||||
*/
|
||||
class Simply_Static_Url_Extractor {
|
||||
|
||||
/**
|
||||
* The following pages were incredibly helpful:
|
||||
* - http://stackoverflow.com/questions/2725156/complete-list-of-html-tag-attributes-which-have-a-url-value
|
||||
* - http://nadeausoftware.com/articles/2008/01/php_tip_how_extract_urls_web_page
|
||||
* - http://php.net/manual/en/book.dom.php
|
||||
*/
|
||||
|
||||
/** @const */
|
||||
protected static $match_elements = array(
|
||||
// HTML
|
||||
'a' => array( 'href', 'urn' ),
|
||||
'base' => array( 'href' ),
|
||||
'form' => array( 'action', 'data' ),
|
||||
'img' => array( 'src', 'usemap', 'longdesc', 'dynsrc', 'lowsrc' ),
|
||||
'link' => array( 'href' ),
|
||||
|
||||
'applet' => array( 'code', 'codebase', 'archive', 'object' ),
|
||||
'area' => array( 'href' ),
|
||||
'body' => array( 'background', 'credits', 'instructions', 'logo' ),
|
||||
'input' => array( 'src', 'usemap', 'dynsrc', 'lowsrc', 'action', 'formaction' ),
|
||||
|
||||
'blockquote' => array( 'cite' ),
|
||||
'del' => array( 'cite' ),
|
||||
'frame' => array( 'longdesc', 'src' ),
|
||||
'head' => array( 'profile' ),
|
||||
'iframe' => array( 'longdesc', 'src' ),
|
||||
'ins' => array( 'cite' ),
|
||||
'object' => array( 'archive', 'classid', 'codebase', 'data', 'usemap' ),
|
||||
'q' => array( 'cite' ),
|
||||
'script' => array( 'src' ),
|
||||
|
||||
'audio' => array( 'src' ),
|
||||
'command' => array( 'icon' ),
|
||||
'embed' => array( 'src', 'code', 'pluginspage' ),
|
||||
'event-source' => array( 'src' ),
|
||||
'html' => array( 'manifest', 'background', 'xmlns' ),
|
||||
'source' => array( 'src' ),
|
||||
'video' => array( 'src', 'poster' ),
|
||||
|
||||
'bgsound' => array( 'src' ),
|
||||
'div' => array( 'href', 'src' ),
|
||||
'ilayer' => array( 'src' ),
|
||||
'table' => array( 'background' ),
|
||||
'td' => array( 'background' ),
|
||||
'th' => array( 'background' ),
|
||||
'layer' => array( 'src' ),
|
||||
'xml' => array( 'src' ),
|
||||
|
||||
'button' => array( 'action', 'formaction' ),
|
||||
'datalist' => array( 'data' ),
|
||||
'select' => array( 'data' ),
|
||||
|
||||
'access' => array( 'path' ),
|
||||
'card' => array( 'onenterforward', 'onenterbackward', 'ontimer' ),
|
||||
'go' => array( 'href' ),
|
||||
'option' => array( 'onpick' ),
|
||||
'template' => array( 'onenterforward', 'onenterbackward', 'ontimer' ),
|
||||
'wml' => array( 'xmlns' )
|
||||
);
|
||||
|
||||
// /** @const */
|
||||
// protected static $match_metas = array(
|
||||
// 'content-base',
|
||||
// 'content-location',
|
||||
// 'referer',
|
||||
// 'location',
|
||||
// 'refresh',
|
||||
// );
|
||||
|
||||
/**
|
||||
* The URL request response
|
||||
*
|
||||
* @var Simply_Static_Url_Response
|
||||
*/
|
||||
protected $response;
|
||||
|
||||
/**
|
||||
* The url of the site
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $extracted_urls = array();
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param string $page_contents The contents of the html/css/etc. page/file
|
||||
* @param string $url The url of the site
|
||||
*/
|
||||
public function __construct( $response ) {
|
||||
$this->response = $response;
|
||||
}
|
||||
|
||||
/**
|
||||
* Extracts URLs from the response
|
||||
*
|
||||
* Returns a list of unique URLs from the body of the response. It only
|
||||
* extracts URLs from the same domain, either absolute urls or relative urls
|
||||
* that are then converted to absolute urls.
|
||||
*
|
||||
* Note that no validation is performed on whether the URLs would actually
|
||||
* return a 200/OK response.
|
||||
*
|
||||
* @return array $urls
|
||||
*/
|
||||
public function extract_urls() {
|
||||
|
||||
if ( $this->response->is_html() ) {
|
||||
$this->extract_urls_from_html();
|
||||
}
|
||||
|
||||
if ( $this->response->is_css() ) {
|
||||
$this->extract_urls_from_css( $this->response->body );
|
||||
}
|
||||
|
||||
return array_unique( $this->extracted_urls );
|
||||
}
|
||||
|
||||
/**
|
||||
* Loops through all elements in the DOM to pull out URLs
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
private function extract_urls_from_html() {
|
||||
|
||||
$doc = new DOMDocument();
|
||||
libxml_use_internal_errors( true );
|
||||
$doc->loadHTML( $this->response->body );
|
||||
libxml_use_internal_errors( false );
|
||||
// get all elements on the page
|
||||
$elements = $doc->getElementsByTagName( '*' );
|
||||
foreach ( $elements as $element ) {
|
||||
$tag_name = $element->tagName;
|
||||
|
||||
if( $tag_name === 'style' ) {
|
||||
$this->extract_urls_from_css( $element->nodeValue );
|
||||
} else {
|
||||
$style_attr_value = $element->getAttribute( 'style' );
|
||||
if ( $style_attr_value !== '' ) {
|
||||
$this->extract_urls_from_css( $style_attr_value );
|
||||
}
|
||||
|
||||
if ( array_key_exists( $tag_name, self::$match_elements ) ) {
|
||||
$match_attributes = self::$match_elements[ $tag_name ];
|
||||
foreach ( $match_attributes as $attribute_name ) {
|
||||
$extracted_url = $element->getAttribute( $attribute_name );
|
||||
$this->add_to_extracted_urls( $extracted_url );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Use regex to extract URLs on CSS pages
|
||||
*
|
||||
* URLs in CSS follow three basic patterns:
|
||||
* - @import "common.css" screen, projection;
|
||||
* - @import url("fineprint.css") print;
|
||||
* - background-image: url(image.png);
|
||||
*
|
||||
* URLs are either contained within url(), part of an @import statement,
|
||||
* or both.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
private function extract_urls_from_css( $text ) {
|
||||
|
||||
$patterns = array( "/url\(\s*[\"']?([^)\"']+)/", // url()
|
||||
"/@import\s+[\"']([^\"']+)/" ); // @import w/o url()
|
||||
|
||||
foreach ( $patterns as $pattern ) {
|
||||
if ( preg_match_all( $pattern, $text, $matches, PREG_PATTERN_ORDER ) === false ) {
|
||||
return;
|
||||
}
|
||||
|
||||
foreach ( $matches[1] as $match ) {
|
||||
if ( !empty($match) ) {
|
||||
$this->add_to_extracted_urls( $match );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Add an extracted URL (relative or absolute) to the extracted URLs array
|
||||
*
|
||||
* Absolute URLs are only added if the scheme/host matches the site it was
|
||||
* extracted from. Relative URLs are converted to absolute URLs before being
|
||||
* added to the array.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
private function add_to_extracted_urls( $extracted_url ) {
|
||||
$absolute_url = sist_relative_to_absolute_url( $extracted_url, $this->response->url );
|
||||
|
||||
if ( $absolute_url && sist_is_local_url( $absolute_url ) ) {
|
||||
$this->extracted_urls[] = sist_remove_params_and_fragment( $absolute_url );
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
<?php if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly
|
||||
|
||||
/**
|
||||
* Simply Static URL fetcher class
|
||||
*
|
||||
* @package Simply_Static
|
||||
*/
|
||||
class Simply_Static_Url_Fetcher {
|
||||
|
||||
/**
|
||||
* Timeout for fetching URLs
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
const TIMEOUT = 300;
|
||||
|
||||
/**
|
||||
* Fetch the URL and return a WP_Error if we get one, otherwise a Response class.
|
||||
*
|
||||
* @return WP_Error|Simply_Static_Url_Response
|
||||
*/
|
||||
public static function fetch( $url ) {
|
||||
// Don't process URLs that don't match the URL of this WordPress installation
|
||||
if ( ! sist_is_local_url( $url ) ) {
|
||||
return new WP_Error( 'attempting_to_fetch_remote_url', sprintf( __( "Attempting to fetch remote URL: %s", Simply_Static::SLUG ), $url ) );
|
||||
}
|
||||
|
||||
$response = wp_remote_get( $url, array(
|
||||
'timeout' => self::TIMEOUT,
|
||||
'sslverify' => false, // not verifying SSL because all calls are local
|
||||
'redirection' => 0 // disable redirection
|
||||
) );
|
||||
|
||||
if ( is_wp_error( $response ) ) {
|
||||
return $response;
|
||||
} else {
|
||||
return new Simply_Static_Url_Response( $url, $response );
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,132 @@
|
||||
<?php if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly
|
||||
|
||||
/**
|
||||
* Simply Static URL response class
|
||||
*
|
||||
* @package Simply_Static
|
||||
*/
|
||||
|
||||
class Simply_Static_Url_Response {
|
||||
|
||||
/**
|
||||
* The URI resource
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public $url;
|
||||
|
||||
/**
|
||||
* The headers from the response
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public $headers = array();
|
||||
|
||||
/**
|
||||
* The body content of the response
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public $body = '';
|
||||
|
||||
/**
|
||||
* The code from the response, e.g. 200
|
||||
*
|
||||
* @var integer
|
||||
*/
|
||||
public $code = null;
|
||||
|
||||
/**
|
||||
* The message from the response, e.g. 'OK'
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public $message = '';
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param string $url URI resource
|
||||
*/
|
||||
public function __construct( $url, $response ) {
|
||||
$this->url = $url;
|
||||
$this->headers = $response['headers'];
|
||||
$this->body = $response['body'];
|
||||
$this->code = $response['response']['code'];
|
||||
$this->message = $response['response']['message'];
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the content type
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function get_content_type() {
|
||||
return isset( $this->headers['content-type'] ) ? $this->headers['content-type'] : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if content type is html
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function is_html() {
|
||||
return stripos( $this->get_content_type(), 'html' ) !== false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if content type is html
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function is_css() {
|
||||
return stripos( $this->get_content_type(), 'css' ) !== false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks for a location header (redirection URL). Returns an empty string if
|
||||
* it doesn't find one.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function get_redirect_url() {
|
||||
return isset( $this->headers['location'] ) ? $this->headers['location'] : '';
|
||||
}
|
||||
|
||||
// /**
|
||||
// * Removes WordPress-specific meta tags
|
||||
// *
|
||||
// * @return void
|
||||
// */
|
||||
// protected function cleanup() {
|
||||
// if ( $this->is_html() ) {
|
||||
// $response_body = preg_replace( '/<link rel=["\' ](pingback|alternate|EditURI|wlwmanifest|index|profile|prev)["\' ](.*?)>/si', '', $this->get_response_body() );
|
||||
// $response_body = preg_replace( '/<meta name=["\' ]generator["\' ](.*?)>/si', '', $response_body );
|
||||
// $this->set_response_body( $response_body );
|
||||
// }
|
||||
// }
|
||||
|
||||
/**
|
||||
* Extracts the list of unique URLs
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function extract_urls() {
|
||||
$extractor = new Simply_Static_Url_Extractor( $this );
|
||||
return $extractor->extract_urls();
|
||||
}
|
||||
|
||||
/**
|
||||
* Replaces base URL
|
||||
*
|
||||
* @param string $origin_url
|
||||
* @param string $destination_url
|
||||
* @return void
|
||||
*/
|
||||
public function replace_url( $origin_url, $destination_url ) {
|
||||
if ( $this->is_html() ) {
|
||||
$response_body = str_replace( $origin_url, $destination_url, $this->body );
|
||||
$this->body = $response_body;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,216 @@
|
||||
<?php if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly
|
||||
|
||||
/**
|
||||
* Simply Static view class
|
||||
*
|
||||
* @package Simply_Static
|
||||
*/
|
||||
class Simply_Static_View {
|
||||
|
||||
/**
|
||||
* Base directory for views
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
const DIRECTORY = 'views';
|
||||
|
||||
/**
|
||||
* View script extension
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
const EXTENSION = '.phtml';
|
||||
|
||||
/**
|
||||
* View variables array
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $variables = array();
|
||||
|
||||
/**
|
||||
* Absolute path for view
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $path = null;
|
||||
|
||||
/**
|
||||
* Template file name to render
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $template = null;
|
||||
|
||||
/**
|
||||
* Flashes are quick status messages displayed at the top of the page
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $flashes = array();
|
||||
|
||||
/**
|
||||
* Performs initialization of the absolute path for views
|
||||
*/
|
||||
public function __construct() {
|
||||
// Looking for a basic directory where plugin resides
|
||||
list($plugin_dir) = explode( '/', plugin_basename( __FILE__ ) );
|
||||
|
||||
// making up an absolute path to views directory
|
||||
$path_array = array( WP_PLUGIN_DIR, $plugin_dir, self::DIRECTORY );
|
||||
|
||||
$this->path = implode( '/', $path_array );
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets a layout that will be used later in render() method.
|
||||
*
|
||||
* @param string $template The template filename, without extension
|
||||
* @return Simply_Static_View
|
||||
*/
|
||||
public function set_layout( $layout ) {
|
||||
$this->layout = trailingslashit( $this->path ) . 'layouts/' . $layout . self::EXTENSION;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets a template that will be used later in render() method.
|
||||
*
|
||||
* @param string $template The template filename, without extension
|
||||
* @return Simply_Static_View
|
||||
*/
|
||||
public function set_template( $template ) {
|
||||
$this->template = trailingslashit( $this->path ) . $template . self::EXTENSION;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a value of the option identified by $name
|
||||
*
|
||||
* @param string $name The option name
|
||||
* @return mixed|null
|
||||
*/
|
||||
public function __get( $name ) {
|
||||
$value = array_key_exists( $name, $this->variables ) ? $this->variables[$name] : null;
|
||||
return $value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the view variable identified by $name with the value provided in $value
|
||||
*
|
||||
* @param string $name The variable name
|
||||
* @param mixed $value The variable value
|
||||
* @return Simply_Static_View
|
||||
*/
|
||||
public function __set( $name, $value ) {
|
||||
$this->variables[$name] = $value;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the view variable identified by $name with the value provided in $value
|
||||
*
|
||||
* @param string $name The variable name
|
||||
* @param mixed $value The variable value
|
||||
* @return Simply_Static_View
|
||||
*/
|
||||
public function assign( $name, $value ) {
|
||||
return $this->__set( $name, $value );
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a flash message to be displayed at the top of the page
|
||||
*
|
||||
* @param string $type The type of message to be displayed
|
||||
* @param string $message The message to be displayed
|
||||
* @return void
|
||||
*/
|
||||
public function add_flash( $type, $message ) {
|
||||
array_push( $this->flashes, array( 'type' => $type, 'message' => $message ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the layout (if available) or template. Checks to make sure that
|
||||
* the file exists and is readable.
|
||||
*
|
||||
* @return string|WP_Error
|
||||
*/
|
||||
private function get_renderable_file() {
|
||||
|
||||
// must include a template
|
||||
if ( ! is_readable( $this->template ) ) {
|
||||
return new WP_Error( 'invalid_template', sprintf( __( "Can't find view template: %s", $this->slug ), $this->template ) );
|
||||
}
|
||||
|
||||
// layouts are optional. if no layout provided, use the template by itself.
|
||||
if ( $this->layout ) {
|
||||
if ( ! is_readable( $this->layout ) ) {
|
||||
return new WP_Error( 'invalid_layout', sprintf( __( "Can't find view layout: %s", $this->slug ), $this->layout ) );
|
||||
} else {
|
||||
// the layout should include the template
|
||||
return $this->layout;
|
||||
}
|
||||
} else {
|
||||
return $this->template;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Check Simply_Static's system requirements and add errors as necessary.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
private function check_for_errors() {
|
||||
|
||||
$errors = Simply_Static::instance()->check_system_requirements();
|
||||
|
||||
foreach ( $errors as $field ) {
|
||||
foreach ( $field as $error ) {
|
||||
$this->add_flash( 'error', $error );
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Renders the view script.
|
||||
*
|
||||
* @return Simply_Static_View|WP_Error
|
||||
*/
|
||||
public function render() {
|
||||
|
||||
$this->check_for_errors();
|
||||
|
||||
$file = $this->get_renderable_file();
|
||||
|
||||
if ( is_wp_error( $file ) ) {
|
||||
return $file;
|
||||
} else {
|
||||
include $file;
|
||||
return $this;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the view as a string.
|
||||
*
|
||||
* @return string|WP_Error
|
||||
*/
|
||||
public function render_to_string() {
|
||||
|
||||
$file = $this->get_renderable_file();
|
||||
|
||||
if ( is_wp_error( $file ) ) {
|
||||
return $file;
|
||||
} else {
|
||||
ob_start();
|
||||
include $file;
|
||||
return ob_get_clean();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
Executable
+420
@@ -0,0 +1,420 @@
|
||||
<?php if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly
|
||||
|
||||
/**
|
||||
* The core plugin class
|
||||
*
|
||||
* @package Simply_Static
|
||||
*/
|
||||
class Simply_Static {
|
||||
/**
|
||||
* Plugin version
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
const VERSION = '2.0.0';
|
||||
|
||||
/**
|
||||
* The slug of the plugin; used in actions, filters, i18n, etc.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
const SLUG = 'simply-static-s3';
|
||||
|
||||
/**
|
||||
* Singleton instance
|
||||
*
|
||||
* @var Simply_Static
|
||||
*/
|
||||
protected static $instance = null;
|
||||
|
||||
/**
|
||||
* An instance of the options structure containing all options for this plugin
|
||||
*
|
||||
* @var Simply_Static_Options
|
||||
*/
|
||||
protected $options = null;
|
||||
|
||||
/**
|
||||
* View object
|
||||
*
|
||||
* @var Simply_Static_View
|
||||
*/
|
||||
protected $view = null;
|
||||
|
||||
/**
|
||||
* Disable usage of "new"
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function __construct() {}
|
||||
|
||||
/**
|
||||
* Disable cloning of the class
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function __clone() {}
|
||||
|
||||
/**
|
||||
* Disable unserializing of the class
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function __wakeup() {}
|
||||
|
||||
/**
|
||||
* Return an instance of the Simply Static plugin
|
||||
*
|
||||
* @return Simply_Static
|
||||
*/
|
||||
public static function instance()
|
||||
{
|
||||
if ( null === self::$instance )
|
||||
{
|
||||
self::$instance = new self();
|
||||
self::$instance->includes();
|
||||
self::$instance->options = new Simply_Static_Options( self::SLUG );
|
||||
self::$instance->view = new Simply_Static_View();
|
||||
|
||||
// Load the text domain for i18n
|
||||
add_action( 'plugins_loaded', array( self::$instance, 'load_textdomain' ) );
|
||||
// Enqueue admin styles
|
||||
add_action( 'admin_enqueue_scripts', array( self::$instance, 'enqueue_admin_styles' ) );
|
||||
// Enqueue admin scripts
|
||||
add_action( 'admin_enqueue_scripts', array( self::$instance, 'enqueue_admin_scripts' ) );
|
||||
// Add the options page and menu item.
|
||||
add_action( 'admin_menu', array( self::$instance, 'add_plugin_admin_menu' ), 2 );
|
||||
}
|
||||
|
||||
return self::$instance;
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize singleton instance
|
||||
*
|
||||
* @param string $bootstrap_file
|
||||
* @return Simply_Static
|
||||
*/
|
||||
public static function init( $bootstrap_file )
|
||||
{
|
||||
$instance = self::instance();
|
||||
|
||||
// Activation
|
||||
register_activation_hook( $bootstrap_file, array( $instance, 'activate' ) );
|
||||
|
||||
return $instance;
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs activation
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function activate()
|
||||
{
|
||||
// Not installed?
|
||||
if ( null === $this->options->get( 'version' ) ) {
|
||||
$this->options
|
||||
->set( 'version', self::VERSION )
|
||||
->set( 'destination_scheme', sist_get_origin_scheme() )
|
||||
->set( 'destination_host', sist_get_origin_host() )
|
||||
->set( 'temp_files_dir', trailingslashit( plugin_dir_path( dirname( __FILE__ ) ) . 'static-files' ) )
|
||||
->set( 'additional_urls', '' )
|
||||
->set( 'delivery_method', 's3' )
|
||||
->set( 'local_dir', '' )
|
||||
->set( 'delete_temp_files', '1' )
|
||||
->set( 'aws_s3_bucket', '' )
|
||||
->set( 'aws_access_key_id', '' )
|
||||
->set( 'aws_secret_access_key', '' )
|
||||
->set( 'aws_s3_region', 'us-east-1' )
|
||||
->set( 'aws_s3_endpoint', 's3.amazonaws.com' )
|
||||
->save();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Include required files
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
private function includes() {
|
||||
require plugin_dir_path( dirname( __FILE__ ) ) . 'includes/libraries/phpuri.php';
|
||||
require plugin_dir_path( dirname( __FILE__ ) ) . 'includes/libraries/S3.php';
|
||||
require plugin_dir_path( dirname( __FILE__ ) ) . 'includes/class-simply-static-options.php';
|
||||
require plugin_dir_path( dirname( __FILE__ ) ) . 'includes/class-simply-static-view.php';
|
||||
require plugin_dir_path( dirname( __FILE__ ) ) . 'includes/class-simply-static-url-extractor.php';
|
||||
require plugin_dir_path( dirname( __FILE__ ) ) . 'includes/class-simply-static-url-fetcher.php';
|
||||
require plugin_dir_path( dirname( __FILE__ ) ) . 'includes/class-simply-static-url-response.php';
|
||||
require plugin_dir_path( dirname( __FILE__ ) ) . 'includes/class-simply-static-archive-creator.php';
|
||||
require plugin_dir_path( dirname( __FILE__ ) ) . 'includes/misc-functions.php';
|
||||
}
|
||||
|
||||
/**
|
||||
* Enqueue admin-specific style sheets for this plugin's admin pages only
|
||||
*
|
||||
* @return null Return early if no settings page is registered.
|
||||
*/
|
||||
public function enqueue_admin_styles() {
|
||||
// Plugin admin CSS. Tack on plugin version.
|
||||
wp_enqueue_style( self::SLUG . '-admin-styles', plugin_dir_url( dirname( __FILE__ ) ) . 'css/admin.css', array(), self::VERSION );
|
||||
}
|
||||
|
||||
/**
|
||||
* Enqueue admin-specific javascript files for this plugin's admin pages only
|
||||
*
|
||||
* @return null Return early if no settings page is registered.
|
||||
*/
|
||||
public function enqueue_admin_scripts() {
|
||||
// Plugin admin CSS. Tack on plugin version.
|
||||
wp_enqueue_script( self::SLUG . '-admin-styles', plugin_dir_url( dirname( __FILE__ ) ) . 'js/admin.js', array(), self::VERSION );
|
||||
}
|
||||
|
||||
/**
|
||||
* Register the administration menu for this plugin into the WordPress Dashboard menu.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function add_plugin_admin_menu() {
|
||||
// Base 64 encoded SVG image.
|
||||
$icon_svg = 'data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiIHN0YW5kYWxvbmU9Im5vIj8+PHN2ZyAgIHhtbG5zOmRjPSJodHRwOi8vcHVybC5vcmcvZGMvZWxlbWVudHMvMS4xLyIgICB4bWxuczpjYz0iaHR0cDovL2NyZWF0aXZlY29tbW9ucy5vcmcvbnMjIiAgIHhtbG5zOnJkZj0iaHR0cDovL3d3dy53My5vcmcvMTk5OS8wMi8yMi1yZGYtc3ludGF4LW5zIyIgICB4bWxuczpzdmc9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiAgIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgICB4bWxuczpzb2RpcG9kaT0iaHR0cDovL3NvZGlwb2RpLnNvdXJjZWZvcmdlLm5ldC9EVEQvc29kaXBvZGktMC5kdGQiICAgeG1sbnM6aW5rc2NhcGU9Imh0dHA6Ly93d3cuaW5rc2NhcGUub3JnL25hbWVzcGFjZXMvaW5rc2NhcGUiICAgaWQ9InN2ZzM0MzQiICAgdmVyc2lvbj0iMS4xIiAgIGlua3NjYXBlOnZlcnNpb249IjAuOTEgcjEzNzI1IiAgIHdpZHRoPSIxODAiICAgaGVpZ2h0PSIzMDAiICAgdmlld0JveD0iMCAwIDE4MCAzMDAiICAgc29kaXBvZGk6ZG9jbmFtZT0iYm9sdC12ZWN0b3ItZ3JheS5zdmciPiAgPG1ldGFkYXRhICAgICBpZD0ibWV0YWRhdGEzNDQwIj4gICAgPHJkZjpSREY+ICAgICAgPGNjOldvcmsgICAgICAgICByZGY6YWJvdXQ9IiI+ICAgICAgICA8ZGM6Zm9ybWF0PmltYWdlL3N2Zyt4bWw8L2RjOmZvcm1hdD4gICAgICAgIDxkYzp0eXBlICAgICAgICAgICByZGY6cmVzb3VyY2U9Imh0dHA6Ly9wdXJsLm9yZy9kYy9kY21pdHlwZS9TdGlsbEltYWdlIiAvPiAgICAgICAgPGRjOnRpdGxlIC8+ICAgICAgPC9jYzpXb3JrPiAgICA8L3JkZjpSREY+ICA8L21ldGFkYXRhPiAgPGRlZnMgICAgIGlkPSJkZWZzMzQzOCIgLz4gIDxzb2RpcG9kaTpuYW1lZHZpZXcgICAgIHBhZ2Vjb2xvcj0iI2ZmZmZmZiIgICAgIGJvcmRlcmNvbG9yPSIjNjY2NjY2IiAgICAgYm9yZGVyb3BhY2l0eT0iMSIgICAgIG9iamVjdHRvbGVyYW5jZT0iMTAiICAgICBncmlkdG9sZXJhbmNlPSIxMCIgICAgIGd1aWRldG9sZXJhbmNlPSIxMCIgICAgIGlua3NjYXBlOnBhZ2VvcGFjaXR5PSIwIiAgICAgaW5rc2NhcGU6cGFnZXNoYWRvdz0iMiIgICAgIGlua3NjYXBlOndpbmRvdy13aWR0aD0iMTUzNiIgICAgIGlua3NjYXBlOndpbmRvdy1oZWlnaHQ9IjgwMSIgICAgIGlkPSJuYW1lZHZpZXczNDM2IiAgICAgc2hvd2dyaWQ9ImZhbHNlIiAgICAgZml0LW1hcmdpbi10b3A9IjAiICAgICBmaXQtbWFyZ2luLWxlZnQ9IjAiICAgICBmaXQtbWFyZ2luLXJpZ2h0PSIwIiAgICAgZml0LW1hcmdpbi1ib3R0b209IjAiICAgICBpbmtzY2FwZTp6b29tPSIyLjE0MjM3MjkiICAgICBpbmtzY2FwZTpjeD0iOC44Njg2Njc5IiAgICAgaW5rc2NhcGU6Y3k9IjE0Ny41MDAwMSIgICAgIGlua3NjYXBlOndpbmRvdy14PSItOCIgICAgIGlua3NjYXBlOndpbmRvdy15PSItOCIgICAgIGlua3NjYXBlOndpbmRvdy1tYXhpbWl6ZWQ9IjEiICAgICBpbmtzY2FwZTpjdXJyZW50LWxheWVyPSJzdmczNDM0IiAvPiAgPHBhdGggICAgIHN0eWxlPSJmaWxsOiM5Y2ExYTY7ZmlsbC1vcGFjaXR5OjEiICAgICBkPSJNIDM5LjksMjMzLjUgODQuNDMzMzMzLDE2MS4xMzMzMyAzOS45LDE2MS4xMzMzMyAxNDAuMSw2Ni41IGwgLTQ0LjUzMzMzMyw3Mi4zNjY2NyA0NC41MzMzMzMsMCB6IiAgICAgaWQ9InBhdGgzNDQ2IiAgICAgaW5rc2NhcGU6Y29ubmVjdG9yLWN1cnZhdHVyZT0iMCIgICAgIHNvZGlwb2RpOm5vZGV0eXBlcz0iY2NjY2NjYyIgLz48L3N2Zz4=';
|
||||
|
||||
// Add main menu item
|
||||
add_menu_page(
|
||||
__( 'Simply Static S3 Settings', self::SLUG ),
|
||||
__( 'Simply Static S3', self::SLUG ),
|
||||
'manage_options',
|
||||
self::SLUG,
|
||||
array( self::$instance, 'display_generate_page' ),
|
||||
$icon_svg
|
||||
);
|
||||
|
||||
add_submenu_page(
|
||||
self::SLUG,
|
||||
__( 'Generate Static Site', self::SLUG ),
|
||||
__( 'Generate', self::SLUG ),
|
||||
'manage_options',
|
||||
self::SLUG,
|
||||
array( self::$instance, 'display_generate_page' )
|
||||
);
|
||||
|
||||
add_submenu_page(
|
||||
self::SLUG,
|
||||
__( 'Simply Static S3 Settings', self::SLUG ),
|
||||
__( 'Settings', self::SLUG ),
|
||||
'manage_options',
|
||||
self::SLUG . '-options',
|
||||
array( self::$instance, 'display_options_page' )
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Render the page for generating a static site.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function display_generate_page() {
|
||||
if ( $this->check_system_requirements() ) {
|
||||
$this->view->assign( 'system_requirements_check_failed', true );
|
||||
}
|
||||
|
||||
if ( isset( $_POST['generate'] ) ) {
|
||||
$archive_creator = new Simply_Static_Archive_Creator(
|
||||
self::SLUG,
|
||||
$this->options->get( 'destination_scheme' ),
|
||||
$this->options->get( 'destination_host' ),
|
||||
$this->options->get( 'temp_files_dir' ),
|
||||
$this->options->get( 'additional_urls' )
|
||||
);
|
||||
$archive_creator->create_archive();
|
||||
|
||||
// TODO: archive_url could be a WP_Error
|
||||
if ( $this->options->get( 'delivery_method' ) == 'zip' ) {
|
||||
|
||||
$archive_url = $archive_creator->create_zip();
|
||||
if ( is_wp_error( $archive_url ) ) {
|
||||
$error = $archive_url->get_error_message();
|
||||
$this->view->add_flash( 'error', $error );
|
||||
} else {
|
||||
$message = __( 'ZIP archive created: ', self::SLUG );
|
||||
$message .= ' <a href="' . $archive_url . '">' . __( 'Click here to download', self::SLUG ) . '</a>';
|
||||
$this->view->add_flash( 'updated', $message );
|
||||
}
|
||||
|
||||
} elseif ( $this->options->get( 'delivery_method' ) == 'local' ) {
|
||||
|
||||
$local_dir = $this->options->get( 'local_dir' );
|
||||
$result = $archive_creator->copy_static_files( $local_dir );
|
||||
|
||||
if ( is_wp_error( $result ) ) {
|
||||
$error = $result->get_error_message();
|
||||
$this->view->add_flash( 'error', $error );
|
||||
} else {
|
||||
$message = __( 'Static files copied to: ' . $local_dir, self::SLUG );
|
||||
$this->view->add_flash( 'updated', $message );
|
||||
}
|
||||
|
||||
} elseif ( $this->options->get( 'delivery_method' ) == 's3' ) {
|
||||
$bucket = $this->options->get( 'aws_s3_bucket' );
|
||||
$result = $archive_creator->publish_to_s3(
|
||||
$bucket,
|
||||
$this->options->get( 'aws_access_key_id' ),
|
||||
$this->options->get( 'aws_secret_access_key' ),
|
||||
$this->options->get( 'aws_s3_region' ),
|
||||
$this->options->get( 'aws_s3_endpoint' )
|
||||
);
|
||||
if ( is_wp_error( $result ) ) {
|
||||
$error = $result->get_error_message();
|
||||
$this->view->add_flash( 'error', $error );
|
||||
} else {
|
||||
$message = __( 'Site published to S3 bucket: ' . $bucket, self::SLUG );
|
||||
$this->view->add_flash( 'updated', $message );
|
||||
}
|
||||
}
|
||||
|
||||
if ( $this->options->get( 'delete_temp_files' ) == '1' ) {
|
||||
$deleted_successfully = $archive_creator->delete_static_files();
|
||||
}
|
||||
|
||||
$export_log = $archive_creator->get_export_log();
|
||||
$this->view->assign( 'export_log', $export_log );
|
||||
}
|
||||
|
||||
$this->view
|
||||
->set_layout( 'admin' )
|
||||
->set_template( 'generate' )
|
||||
->render();
|
||||
}
|
||||
|
||||
/**
|
||||
* Render the options page.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function display_options_page() {
|
||||
if ( isset( $_POST['save'] ) ) {
|
||||
$this->save_options();
|
||||
$message = __( 'Settings saved.', self::SLUG );
|
||||
$this->view->add_flash( 'updated', $message );
|
||||
}
|
||||
|
||||
$this->view
|
||||
->set_layout( 'admin' )
|
||||
->set_template( 'options' )
|
||||
->assign( 'slug', self::SLUG )
|
||||
->assign( 'origin_scheme', sist_get_origin_scheme() )
|
||||
->assign( 'origin_host', sist_get_origin_host() )
|
||||
->assign( 'destination_scheme', $this->options->get( 'destination_scheme' ) )
|
||||
->assign( 'destination_host', $this->options->get( 'destination_host' ) )
|
||||
->assign( 'temp_files_dir', $this->options->get( 'temp_files_dir' ) )
|
||||
->assign( 'additional_urls', $this->options->get( 'additional_urls' ) )
|
||||
->assign( 'delivery_method', $this->options->get( 'delivery_method' ) )
|
||||
->assign( 'local_dir', $this->options->get( 'local_dir' ) )
|
||||
->assign( 'delete_temp_files', $this->options->get( 'delete_temp_files' ) )
|
||||
->assign( 'aws_s3_bucket', $this->options->get( 'aws_s3_bucket' ) )
|
||||
->assign( 'aws_access_key_id', $this->options->get( 'aws_access_key_id' ) )
|
||||
->assign( 'aws_secret_access_key', $this->options->get( 'aws_secret_access_key' ) )
|
||||
->assign( 'aws_s3_region', $this->options->get( 'aws_s3_region' ) )
|
||||
->assign( 'aws_s3_endpoint', $this->options->get( 'aws_s3_endpoint' ) )
|
||||
->render();
|
||||
}
|
||||
|
||||
/**
|
||||
* Save the options from the options page.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function save_options() {
|
||||
$this->options
|
||||
->set( 'destination_scheme', filter_input( INPUT_POST, 'destination_scheme' ) )
|
||||
->set( 'destination_host', untrailingslashit( filter_input( INPUT_POST, 'destination_host', FILTER_SANITIZE_URL ) ) )
|
||||
->set( 'temp_files_dir', sist_trailingslashit_unless_blank( filter_input( INPUT_POST, 'temp_files_dir' ) ) )
|
||||
->set( 'additional_urls', filter_input( INPUT_POST, 'additional_urls' ) )
|
||||
->set( 'delivery_method', filter_input( INPUT_POST, 'delivery_method' ) )
|
||||
->set( 'local_dir', sist_trailingslashit_unless_blank( filter_input( INPUT_POST, 'local_dir' ) ) )
|
||||
->set( 'delete_temp_files', filter_input( INPUT_POST, 'delete_temp_files' ) )
|
||||
->set( 'aws_s3_bucket', filter_input( INPUT_POST, 'aws_s3_bucket' ) )
|
||||
->set( 'aws_access_key_id', filter_input( INPUT_POST, 'aws_access_key_id' ) )
|
||||
->set( 'aws_secret_access_key', filter_input( INPUT_POST, 'aws_secret_access_key' ) )
|
||||
->set( 'aws_s3_region', filter_input( INPUT_POST, 'aws_s3_region' ) )
|
||||
->set( 'aws_s3_endpoint', filter_input( INPUT_POST, 'aws_s3_endpoint' ) )
|
||||
->save();
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads the plugin language files
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function load_textdomain() {
|
||||
load_plugin_textdomain(
|
||||
self::SLUG,
|
||||
false,
|
||||
dirname( dirname( plugin_basename( __FILE__ ) ) ) . '/languages/'
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads the plugin language files
|
||||
*
|
||||
* @return array $errors associative array containing errored field names and an array of error messages
|
||||
*/
|
||||
public function check_system_requirements() {
|
||||
$errors = array();
|
||||
|
||||
$destination_host = $this->options->get( 'destination_host' );
|
||||
if ( strlen( $destination_host ) === 0 ) {
|
||||
$errors['destination_host'][] = __( 'Destination URL cannot be blank', self::SLUG );
|
||||
}
|
||||
|
||||
$temp_files_dir = $this->options->get( 'temp_files_dir' );
|
||||
if ( strlen( $temp_files_dir ) === 0 ) {
|
||||
$errors['temp_files_dir'][] = __( 'Temporary Files Directory cannot be blank', self::SLUG );
|
||||
} else {
|
||||
if ( file_exists( $temp_files_dir ) ) {
|
||||
if ( ! is_writeable( $temp_files_dir ) ) {
|
||||
$errors['delivery_method'][] = sprintf( __( 'Temporary Files Directory is not writeable: %s', self::SLUG ), $temp_files_dir );
|
||||
}
|
||||
} else {
|
||||
$errors['delivery_method'][] = sprintf( __( 'Temporary Files Directory does not exist: %s', self::SLUG ), $temp_files_dir );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if ( strlen( get_option( 'permalink_structure' ) ) === 0 ) {
|
||||
$errors['permalink_structure'][] = sprintf( __( "Your site does not have a permalink structure set. You can select one on <a href='%s'>the Permalink Settings page</a>.", self::SLUG ), admin_url( '/options-permalink.php' ) );
|
||||
}
|
||||
|
||||
if ( $this->options->get( 'delivery_method' ) == 's3' ) {
|
||||
if ( strlen( $this->options->get( 'aws_s3_bucket' ) ) == 0 ) {
|
||||
$errors['delivery_method'][] = __( "You haven't configured an Amazon AWS bucket for S3 publishing.", self::SLUG );
|
||||
}
|
||||
if ( strlen( $this->options->get( 'aws_access_key_id' ) ) == 0 || strlen( $this->options->get( 'aws_secret_access_key' ) ) == 0 ) {
|
||||
$errors['delivery_method'][] = __( "You haven't configured Amazon AWS credentials for S3 publishing.", self::SLUG );
|
||||
}
|
||||
}
|
||||
|
||||
if ( $this->options->get( 'delivery_method' ) == 'zip' ) {
|
||||
if ( ! extension_loaded('zip') ) {
|
||||
$errors['delivery_method'][] = __( "Your server does not have the PHP zip extension enabled. Please visit <a href='http://www.php.net/manual/en/book.zip.php'>the PHP zip extension page</a> for more information on how to enable it.", self::SLUG );
|
||||
}
|
||||
}
|
||||
|
||||
if ( $this->options->get( 'delivery_method' ) == 'local' ) {
|
||||
$local_dir = $this->options->get( 'local_dir' );
|
||||
|
||||
if ( strlen( $local_dir ) === 0 ) {
|
||||
$errors['delivery_method'][] = __( 'Local Directory cannot be blank', self::SLUG );
|
||||
} else {
|
||||
if ( file_exists( $local_dir ) ) {
|
||||
if ( ! is_writeable( $local_dir ) ) {
|
||||
$errors['delivery_method'][] = sprintf( __( 'Local Directory is not writeable: %s', self::SLUG ), $local_dir );
|
||||
}
|
||||
} else {
|
||||
$errors['delivery_method'][] = sprintf( __( 'Local Directory does not exist: %s', self::SLUG ), $local_dir );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $errors;
|
||||
}
|
||||
}
|
||||
Executable
+1
@@ -0,0 +1 @@
|
||||
<?php // Silence is golden
|
||||
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,209 @@
|
||||
<?php if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly
|
||||
|
||||
/**
|
||||
* A php library for converting relative urls to absolute.
|
||||
* Website: https://github.com/monkeysuffrage/phpuri
|
||||
*
|
||||
* <pre>
|
||||
* echo phpUri::parse('https://www.google.com/')->join('foo');
|
||||
* //==> https://www.google.com/foo
|
||||
* </pre>
|
||||
*
|
||||
* Licensed under The MIT License
|
||||
* Redistributions of files must retain the above copyright notice.
|
||||
*
|
||||
* @author P Guardiario <pguardiario@gmail.com>
|
||||
* @version 1.0
|
||||
*/
|
||||
|
||||
/**
|
||||
* phpUri
|
||||
*/
|
||||
class phpUri
|
||||
{
|
||||
|
||||
/**
|
||||
* http(s)://
|
||||
* @var string
|
||||
*/
|
||||
public $scheme;
|
||||
|
||||
/**
|
||||
* www.example.com
|
||||
* @var string
|
||||
*/
|
||||
public $authority;
|
||||
|
||||
/**
|
||||
* /search
|
||||
* @var string
|
||||
*/
|
||||
public $path;
|
||||
|
||||
/**
|
||||
* ?q=foo
|
||||
* @var string
|
||||
*/
|
||||
public $query;
|
||||
|
||||
/**
|
||||
* #bar
|
||||
* @var string
|
||||
*/
|
||||
public $fragment;
|
||||
|
||||
private function __construct( $string )
|
||||
{
|
||||
preg_match_all( '/^(([^:\/?#]+):)?(\/\/([^\/?#]*))?([^?#]*)(\?([^#]*))?(#(.*))?$/', $string, $m );
|
||||
$this->scheme = $m[ 2 ][ 0 ];
|
||||
$this->authority = $m[ 4 ][ 0 ];
|
||||
|
||||
/**
|
||||
* CHANGE:
|
||||
* @author Dominik Habichtsberg <Dominik.Habichtsberg@Hbg-IT.de>
|
||||
* @since 24 Mai 2015 10:02 Uhr
|
||||
*
|
||||
* Former code: $this->path = ( empty( $m[ 5 ][ 0 ] ) ) ? '/' : $m[ 5 ][ 0 ];
|
||||
* No tests failed, when the path is empty.
|
||||
* With the former code, the relative urls //g and #s failed
|
||||
*/
|
||||
$this->path = $m[ 5 ][ 0 ];
|
||||
$this->query = $m[ 7 ][ 0 ];
|
||||
$this->fragment = $m[ 9 ][ 0 ];
|
||||
}
|
||||
|
||||
private function to_str()
|
||||
{
|
||||
$ret = '';
|
||||
if ( !empty( $this->scheme ) )
|
||||
{
|
||||
$ret .= "{$this->scheme}:";
|
||||
}
|
||||
|
||||
if ( !empty( $this->authority ) )
|
||||
{
|
||||
$ret .= "//{$this->authority}";
|
||||
}
|
||||
|
||||
$ret .= $this->normalize_path( $this->path );
|
||||
|
||||
if ( !empty( $this->query ) )
|
||||
{
|
||||
$ret .= "?{$this->query}";
|
||||
}
|
||||
|
||||
if ( !empty( $this->fragment ) )
|
||||
{
|
||||
$ret .= "#{$this->fragment}";
|
||||
}
|
||||
|
||||
return $ret;
|
||||
}
|
||||
|
||||
private function normalize_path( $path )
|
||||
{
|
||||
if ( empty( $path ) )
|
||||
{
|
||||
return '';
|
||||
}
|
||||
|
||||
$normalized_path = $path;
|
||||
$normalized_path = preg_replace( '`//+`', '/', $normalized_path, -1, $c0 );
|
||||
$normalized_path = preg_replace( '`^/\\.\\.?/`', '/', $normalized_path, -1, $c1 );
|
||||
$normalized_path = preg_replace( '`/\\.(/|$)`', '/', $normalized_path, -1, $c2 );
|
||||
|
||||
/**
|
||||
* CHANGE:
|
||||
* @author Dominik Habichtsberg <Dominik.Habichtsberg@Hbg-IT.de>
|
||||
* @since 24 Mai 2015 10:05 Uhr
|
||||
* changed limit form -1 to 1, because climbing up the directory-tree failed
|
||||
*/
|
||||
$normalized_path = preg_replace( '`/[^/]*?/\\.\\.(/|$)`', '/', $normalized_path, 1, $c3 );
|
||||
$num_matches = $c0 + $c1 + $c2 + $c3;
|
||||
|
||||
return ( $num_matches > 0 ) ? $this->normalize_path( $normalized_path ) : $normalized_path;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse an url string
|
||||
*
|
||||
* @param string $url the url to parse
|
||||
*
|
||||
* @return phpUri
|
||||
*/
|
||||
public static function parse( $url )
|
||||
{
|
||||
$uri = new phpUri( $url );
|
||||
|
||||
/**
|
||||
* CHANGE:
|
||||
* @author Dominik Habichtsberg <Dominik.Habichtsberg@Hbg-IT.de>
|
||||
* @since 24 Mai 2015 10:25 Uhr
|
||||
* The base-url should always have a path
|
||||
*/
|
||||
if ( empty( $uri->path ) )
|
||||
{
|
||||
$uri->path = '/';
|
||||
}
|
||||
|
||||
return $uri;
|
||||
}
|
||||
|
||||
/**
|
||||
* Join with a relative url
|
||||
*
|
||||
* @param string $relative the relative url to join
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function join( $relative )
|
||||
{
|
||||
$uri = new phpUri( $relative );
|
||||
switch ( TRUE )
|
||||
{
|
||||
case !empty( $uri->scheme ):
|
||||
break;
|
||||
|
||||
case !empty( $uri->authority ):
|
||||
break;
|
||||
|
||||
case empty( $uri->path ):
|
||||
$uri->path = $this->path;
|
||||
if ( empty( $uri->query ) )
|
||||
{
|
||||
$uri->query = $this->query;
|
||||
}
|
||||
break;
|
||||
|
||||
case strpos( $uri->path, '/' ) === 0:
|
||||
break;
|
||||
|
||||
default:
|
||||
$base_path = $this->path;
|
||||
if ( strpos( $base_path, '/' ) === FALSE )
|
||||
{
|
||||
$base_path = '';
|
||||
}
|
||||
else
|
||||
{
|
||||
$base_path = preg_replace( '/\/[^\/]+$/', '/', $base_path );
|
||||
}
|
||||
if ( empty( $base_path ) && empty( $this->authority ) )
|
||||
{
|
||||
$base_path = '/';
|
||||
}
|
||||
$uri->path = $base_path . $uri->path;
|
||||
}
|
||||
|
||||
if ( empty( $uri->scheme ) )
|
||||
{
|
||||
$uri->scheme = $this->scheme;
|
||||
if ( empty( $uri->authority ) )
|
||||
{
|
||||
$uri->authority = $this->authority;
|
||||
}
|
||||
}
|
||||
|
||||
return $uri->to_str();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,156 @@
|
||||
<?php if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly
|
||||
|
||||
/**
|
||||
* Miscellaneous functions for use across the plugin
|
||||
*
|
||||
* @package Simply_Static
|
||||
*/
|
||||
|
||||
// Exit if accessed directly.
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the protocol used for the origin URL
|
||||
*
|
||||
* @return string http or https
|
||||
*/
|
||||
function sist_get_origin_scheme() {
|
||||
return is_ssl() ? 'https' : 'http';
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the host for the origin URL
|
||||
*
|
||||
* @return string host (URL minus the protocol)
|
||||
*/
|
||||
function sist_get_origin_host() {
|
||||
return untrailingslashit( preg_replace( "(^https?://)", "", home_url() ) );
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Echo the selected value for an option tag if the statement is true.
|
||||
*
|
||||
* @return null
|
||||
*/
|
||||
function sist_selected_if( $statement ) {
|
||||
echo ( $statement == true ? 'selected="selected"' : '' );
|
||||
}
|
||||
|
||||
/**
|
||||
* Truncate if a string exceeds a certain length (30 chars by default)
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
function sist_truncate( $string, $length = 30, $omission = '...' ) {
|
||||
return ( strlen( $string ) > $length + 3 ) ? ( substr( $string, 0, $length ) . $omission ) : $string;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Use trailingslashit unless the string is empty
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
function sist_trailingslashit_unless_blank( $string ) {
|
||||
return $string === '' ? $string : trailingslashit( $string );
|
||||
}
|
||||
|
||||
/**
|
||||
* Dump an object to error_log
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
function sist_error_log( $object=null ){
|
||||
ob_start();
|
||||
var_dump( $object );
|
||||
$contents = ob_get_contents();
|
||||
ob_end_clean();
|
||||
error_log( $contents );
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Given a URL extracted from a page, return an absolute URL
|
||||
*
|
||||
* Takes a URL (e.g. /test) extracted from a page (e.g. http://foo.com/bar/) and
|
||||
* returns an absolute URL (e.g. http://foo.com/bar/test). Absolute URLs are
|
||||
* returned as-is.
|
||||
*
|
||||
* A null value is returned in the event that the extracted_url is blank or it's
|
||||
* unable to be parsed.
|
||||
*
|
||||
* @param string $extracted_url Relative or absolute URL extracted from page
|
||||
* @param string $page_url URL of page
|
||||
* @return string|null Absolute URL, or null
|
||||
*/
|
||||
function sist_relative_to_absolute_url( $extracted_url, $page_url ) {
|
||||
|
||||
$extracted_url = trim( $extracted_url );
|
||||
|
||||
if ( $extracted_url === '' ) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$parsed_extracted_url = parse_url( $extracted_url );
|
||||
|
||||
// parse_url can sometimes return false; bail if it does
|
||||
if ( $parsed_extracted_url === false ) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if ( isset( $parsed_extracted_url['host'] ) ) {
|
||||
|
||||
return $extracted_url;
|
||||
|
||||
} elseif ( isset( $parsed_extracted_url['scheme'] ) ) {
|
||||
|
||||
// examples of schemes without hosts: java:, data:
|
||||
return $extracted_url;
|
||||
|
||||
} else { // no host on extracted page (might be relative url)
|
||||
|
||||
$path = isset( $parsed_extracted_url['path'] ) ? $parsed_extracted_url['path'] : '';
|
||||
|
||||
// Check for a bug in PHP <= 5.4.7 where URLs starting
|
||||
// with '//' are identified as a path
|
||||
// http://php.net/manual/en/function.parse-url.php#example-4617
|
||||
if ( substr( $path, 0, 2 ) === '//' ) {
|
||||
|
||||
return $extracted_url;
|
||||
|
||||
} else {
|
||||
|
||||
$query = isset( $parsed_extracted_url['query'] ) ? '?' . $parsed_extracted_url['query'] : '';
|
||||
$fragment = isset( $parsed_extracted_url['fragment'] ) ? '#' . $parsed_extracted_url['fragment'] : '';
|
||||
|
||||
// turn our relative url into an absolute url
|
||||
$extracted_url = phpUri::parse( $page_url )->join( $path . $query . $fragment );
|
||||
|
||||
return $extracted_url;
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if URL starts with same URL as WordPress installation
|
||||
*
|
||||
* @param string $url URL to check
|
||||
* @return boolean true if URL is local, false otherwise
|
||||
*/
|
||||
function sist_is_local_url( $url ) {
|
||||
return ( stripos( $url, home_url() ) === 0 );
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a URL w/o the query string or fragment (i.e. nothing after the path)
|
||||
*
|
||||
* @param string $url URL to remove query string/fragment from
|
||||
* @return string URL without query string/fragment
|
||||
*/
|
||||
function sist_remove_params_and_fragment( $url ) {
|
||||
return preg_replace('/(\?|#).*/', '', $url);
|
||||
}
|
||||
Reference in new issue
Block a user