Initial commit
This commit is contained in:
commit
f9f65dc84d
23 files changed
+5074
No files matched your search
@@ -0,0 +1,64 @@
|
||||
#sistContainer {
|
||||
margin-right: 310px;
|
||||
}
|
||||
|
||||
#sistContent {
|
||||
width: 100%;
|
||||
float: left;
|
||||
min-width: 600px;
|
||||
}
|
||||
|
||||
#sistSidebar {
|
||||
float: right;
|
||||
margin-right: -310px;
|
||||
width: 290px;
|
||||
}
|
||||
|
||||
/* Generate page */
|
||||
|
||||
.export-log {
|
||||
height: 200px;
|
||||
overflow: auto;
|
||||
border: 1px solid #DFDFDF;
|
||||
color: #000;
|
||||
background: #fff;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.export-log pre {
|
||||
margin: 0;
|
||||
padding: 3px 4px;
|
||||
}
|
||||
|
||||
/* Options page */
|
||||
|
||||
.tab-pane, tr.delivery-method {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.tab-pane.active, tr.delivery-method.active {
|
||||
display: table-row;
|
||||
}
|
||||
|
||||
select:disabled, select.disabled {
|
||||
border-color: rgba(222,222,222,.75);
|
||||
background: rgba(255,255,255,.5);
|
||||
color: rgba(51,51,51,.5);
|
||||
}
|
||||
|
||||
.help-block {
|
||||
display: block;
|
||||
margin-top: 5px;
|
||||
margin-bottom: 10px;
|
||||
color: #737373;
|
||||
}
|
||||
|
||||
/* Mailchimp Form CSS */
|
||||
|
||||
/* Mailchimp original CSS at:
|
||||
http://cdn-images.mailchimp.com/embedcode/slim-081711.css
|
||||
*/
|
||||
#mc_embed_signup input {border:1px solid #999; -webkit-appearance:none;}
|
||||
#mc_embed_signup input:focus {border-color:#333;}
|
||||
#mc_embed_signup .clear {clear:none; display:inline;}
|
||||
#mc_embed_signup input.email {display:block; padding:8px 0; margin:0 4% 10px 0; text-indent:5px; width:58%; min-width:130px; width:100%;}
|
||||
@@ -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);
|
||||
}
|
||||
+40
@@ -0,0 +1,40 @@
|
||||
'use strict';
|
||||
jQuery( document ).ready( function() {
|
||||
|
||||
// show / hide tabs:
|
||||
jQuery( '#sistTabs' ).find( 'a' ).click( function() {
|
||||
jQuery( '#sistTabs' ).find( 'a' ).removeClass( 'nav-tab-active' );
|
||||
jQuery( '.tab-pane' ).removeClass( 'active' );
|
||||
|
||||
var id = jQuery( this ).attr( 'id' ).replace( '-tab', '' );
|
||||
jQuery( '#' + id ).addClass( 'active' );
|
||||
jQuery( this ).addClass( 'nav-tab-active' );
|
||||
});
|
||||
|
||||
// set active tab on page load:
|
||||
var activeTab = window.location.hash.replace( '#tab-', '' );
|
||||
|
||||
// if no tab hash, default to the first tab
|
||||
if ( activeTab === '' ) {
|
||||
activeTab = jQuery( '.tab-pane' ).attr( 'id' );
|
||||
}
|
||||
|
||||
jQuery( '#' + activeTab ).addClass( 'active' );
|
||||
jQuery( '#' + activeTab + '-tab' ).addClass( 'nav-tab-active' );
|
||||
|
||||
// pretend the user clicked on the active tab
|
||||
jQuery( '.nav-tab-active' ).click();
|
||||
|
||||
// -----------------------------------------------------------------------//
|
||||
|
||||
// delivery method selection:
|
||||
jQuery( '#deliveryMethod' ).change(function() {
|
||||
var selected = jQuery( this ).val();
|
||||
jQuery( '.delivery-method' ).removeClass( 'active' );
|
||||
jQuery( '.' + selected + '.delivery-method' ).addClass( 'active ');
|
||||
});
|
||||
|
||||
// pretend the user selected a value
|
||||
jQuery(' #deliveryMethod' ).change();
|
||||
|
||||
});
|
||||
Whitespace-only changes.
Executable
+339
@@ -0,0 +1,339 @@
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
Version 2, June 1991
|
||||
|
||||
Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
|
||||
Preamble
|
||||
|
||||
The licenses for most software are designed to take away your
|
||||
freedom to share and change it. By contrast, the GNU General Public
|
||||
License is intended to guarantee your freedom to share and change free
|
||||
software--to make sure the software is free for all its users. This
|
||||
General Public License applies to most of the Free Software
|
||||
Foundation's software and to any other program whose authors commit to
|
||||
using it. (Some other Free Software Foundation software is covered by
|
||||
the GNU Lesser General Public License instead.) You can apply it to
|
||||
your programs, too.
|
||||
|
||||
When we speak of free software, we are referring to freedom, not
|
||||
price. Our General Public Licenses are designed to make sure that you
|
||||
have the freedom to distribute copies of free software (and charge for
|
||||
this service if you wish), that you receive source code or can get it
|
||||
if you want it, that you can change the software or use pieces of it
|
||||
in new free programs; and that you know you can do these things.
|
||||
|
||||
To protect your rights, we need to make restrictions that forbid
|
||||
anyone to deny you these rights or to ask you to surrender the rights.
|
||||
These restrictions translate to certain responsibilities for you if you
|
||||
distribute copies of the software, or if you modify it.
|
||||
|
||||
For example, if you distribute copies of such a program, whether
|
||||
gratis or for a fee, you must give the recipients all the rights that
|
||||
you have. You must make sure that they, too, receive or can get the
|
||||
source code. And you must show them these terms so they know their
|
||||
rights.
|
||||
|
||||
We protect your rights with two steps: (1) copyright the software, and
|
||||
(2) offer you this license which gives you legal permission to copy,
|
||||
distribute and/or modify the software.
|
||||
|
||||
Also, for each author's protection and ours, we want to make certain
|
||||
that everyone understands that there is no warranty for this free
|
||||
software. If the software is modified by someone else and passed on, we
|
||||
want its recipients to know that what they have is not the original, so
|
||||
that any problems introduced by others will not reflect on the original
|
||||
authors' reputations.
|
||||
|
||||
Finally, any free program is threatened constantly by software
|
||||
patents. We wish to avoid the danger that redistributors of a free
|
||||
program will individually obtain patent licenses, in effect making the
|
||||
program proprietary. To prevent this, we have made it clear that any
|
||||
patent must be licensed for everyone's free use or not licensed at all.
|
||||
|
||||
The precise terms and conditions for copying, distribution and
|
||||
modification follow.
|
||||
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
||||
|
||||
0. This License applies to any program or other work which contains
|
||||
a notice placed by the copyright holder saying it may be distributed
|
||||
under the terms of this General Public License. The "Program", below,
|
||||
refers to any such program or work, and a "work based on the Program"
|
||||
means either the Program or any derivative work under copyright law:
|
||||
that is to say, a work containing the Program or a portion of it,
|
||||
either verbatim or with modifications and/or translated into another
|
||||
language. (Hereinafter, translation is included without limitation in
|
||||
the term "modification".) Each licensee is addressed as "you".
|
||||
|
||||
Activities other than copying, distribution and modification are not
|
||||
covered by this License; they are outside its scope. The act of
|
||||
running the Program is not restricted, and the output from the Program
|
||||
is covered only if its contents constitute a work based on the
|
||||
Program (independent of having been made by running the Program).
|
||||
Whether that is true depends on what the Program does.
|
||||
|
||||
1. You may copy and distribute verbatim copies of the Program's
|
||||
source code as you receive it, in any medium, provided that you
|
||||
conspicuously and appropriately publish on each copy an appropriate
|
||||
copyright notice and disclaimer of warranty; keep intact all the
|
||||
notices that refer to this License and to the absence of any warranty;
|
||||
and give any other recipients of the Program a copy of this License
|
||||
along with the Program.
|
||||
|
||||
You may charge a fee for the physical act of transferring a copy, and
|
||||
you may at your option offer warranty protection in exchange for a fee.
|
||||
|
||||
2. You may modify your copy or copies of the Program or any portion
|
||||
of it, thus forming a work based on the Program, and copy and
|
||||
distribute such modifications or work under the terms of Section 1
|
||||
above, provided that you also meet all of these conditions:
|
||||
|
||||
a) You must cause the modified files to carry prominent notices
|
||||
stating that you changed the files and the date of any change.
|
||||
|
||||
b) You must cause any work that you distribute or publish, that in
|
||||
whole or in part contains or is derived from the Program or any
|
||||
part thereof, to be licensed as a whole at no charge to all third
|
||||
parties under the terms of this License.
|
||||
|
||||
c) If the modified program normally reads commands interactively
|
||||
when run, you must cause it, when started running for such
|
||||
interactive use in the most ordinary way, to print or display an
|
||||
announcement including an appropriate copyright notice and a
|
||||
notice that there is no warranty (or else, saying that you provide
|
||||
a warranty) and that users may redistribute the program under
|
||||
these conditions, and telling the user how to view a copy of this
|
||||
License. (Exception: if the Program itself is interactive but
|
||||
does not normally print such an announcement, your work based on
|
||||
the Program is not required to print an announcement.)
|
||||
|
||||
These requirements apply to the modified work as a whole. If
|
||||
identifiable sections of that work are not derived from the Program,
|
||||
and can be reasonably considered independent and separate works in
|
||||
themselves, then this License, and its terms, do not apply to those
|
||||
sections when you distribute them as separate works. But when you
|
||||
distribute the same sections as part of a whole which is a work based
|
||||
on the Program, the distribution of the whole must be on the terms of
|
||||
this License, whose permissions for other licensees extend to the
|
||||
entire whole, and thus to each and every part regardless of who wrote it.
|
||||
|
||||
Thus, it is not the intent of this section to claim rights or contest
|
||||
your rights to work written entirely by you; rather, the intent is to
|
||||
exercise the right to control the distribution of derivative or
|
||||
collective works based on the Program.
|
||||
|
||||
In addition, mere aggregation of another work not based on the Program
|
||||
with the Program (or with a work based on the Program) on a volume of
|
||||
a storage or distribution medium does not bring the other work under
|
||||
the scope of this License.
|
||||
|
||||
3. You may copy and distribute the Program (or a work based on it,
|
||||
under Section 2) in object code or executable form under the terms of
|
||||
Sections 1 and 2 above provided that you also do one of the following:
|
||||
|
||||
a) Accompany it with the complete corresponding machine-readable
|
||||
source code, which must be distributed under the terms of Sections
|
||||
1 and 2 above on a medium customarily used for software interchange; or,
|
||||
|
||||
b) Accompany it with a written offer, valid for at least three
|
||||
years, to give any third party, for a charge no more than your
|
||||
cost of physically performing source distribution, a complete
|
||||
machine-readable copy of the corresponding source code, to be
|
||||
distributed under the terms of Sections 1 and 2 above on a medium
|
||||
customarily used for software interchange; or,
|
||||
|
||||
c) Accompany it with the information you received as to the offer
|
||||
to distribute corresponding source code. (This alternative is
|
||||
allowed only for noncommercial distribution and only if you
|
||||
received the program in object code or executable form with such
|
||||
an offer, in accord with Subsection b above.)
|
||||
|
||||
The source code for a work means the preferred form of the work for
|
||||
making modifications to it. For an executable work, complete source
|
||||
code means all the source code for all modules it contains, plus any
|
||||
associated interface definition files, plus the scripts used to
|
||||
control compilation and installation of the executable. However, as a
|
||||
special exception, the source code distributed need not include
|
||||
anything that is normally distributed (in either source or binary
|
||||
form) with the major components (compiler, kernel, and so on) of the
|
||||
operating system on which the executable runs, unless that component
|
||||
itself accompanies the executable.
|
||||
|
||||
If distribution of executable or object code is made by offering
|
||||
access to copy from a designated place, then offering equivalent
|
||||
access to copy the source code from the same place counts as
|
||||
distribution of the source code, even though third parties are not
|
||||
compelled to copy the source along with the object code.
|
||||
|
||||
4. You may not copy, modify, sublicense, or distribute the Program
|
||||
except as expressly provided under this License. Any attempt
|
||||
otherwise to copy, modify, sublicense or distribute the Program is
|
||||
void, and will automatically terminate your rights under this License.
|
||||
However, parties who have received copies, or rights, from you under
|
||||
this License will not have their licenses terminated so long as such
|
||||
parties remain in full compliance.
|
||||
|
||||
5. You are not required to accept this License, since you have not
|
||||
signed it. However, nothing else grants you permission to modify or
|
||||
distribute the Program or its derivative works. These actions are
|
||||
prohibited by law if you do not accept this License. Therefore, by
|
||||
modifying or distributing the Program (or any work based on the
|
||||
Program), you indicate your acceptance of this License to do so, and
|
||||
all its terms and conditions for copying, distributing or modifying
|
||||
the Program or works based on it.
|
||||
|
||||
6. Each time you redistribute the Program (or any work based on the
|
||||
Program), the recipient automatically receives a license from the
|
||||
original licensor to copy, distribute or modify the Program subject to
|
||||
these terms and conditions. You may not impose any further
|
||||
restrictions on the recipients' exercise of the rights granted herein.
|
||||
You are not responsible for enforcing compliance by third parties to
|
||||
this License.
|
||||
|
||||
7. If, as a consequence of a court judgment or allegation of patent
|
||||
infringement or for any other reason (not limited to patent issues),
|
||||
conditions are imposed on you (whether by court order, agreement or
|
||||
otherwise) that contradict the conditions of this License, they do not
|
||||
excuse you from the conditions of this License. If you cannot
|
||||
distribute so as to satisfy simultaneously your obligations under this
|
||||
License and any other pertinent obligations, then as a consequence you
|
||||
may not distribute the Program at all. For example, if a patent
|
||||
license would not permit royalty-free redistribution of the Program by
|
||||
all those who receive copies directly or indirectly through you, then
|
||||
the only way you could satisfy both it and this License would be to
|
||||
refrain entirely from distribution of the Program.
|
||||
|
||||
If any portion of this section is held invalid or unenforceable under
|
||||
any particular circumstance, the balance of the section is intended to
|
||||
apply and the section as a whole is intended to apply in other
|
||||
circumstances.
|
||||
|
||||
It is not the purpose of this section to induce you to infringe any
|
||||
patents or other property right claims or to contest validity of any
|
||||
such claims; this section has the sole purpose of protecting the
|
||||
integrity of the free software distribution system, which is
|
||||
implemented by public license practices. Many people have made
|
||||
generous contributions to the wide range of software distributed
|
||||
through that system in reliance on consistent application of that
|
||||
system; it is up to the author/donor to decide if he or she is willing
|
||||
to distribute software through any other system and a licensee cannot
|
||||
impose that choice.
|
||||
|
||||
This section is intended to make thoroughly clear what is believed to
|
||||
be a consequence of the rest of this License.
|
||||
|
||||
8. If the distribution and/or use of the Program is restricted in
|
||||
certain countries either by patents or by copyrighted interfaces, the
|
||||
original copyright holder who places the Program under this License
|
||||
may add an explicit geographical distribution limitation excluding
|
||||
those countries, so that distribution is permitted only in or among
|
||||
countries not thus excluded. In such case, this License incorporates
|
||||
the limitation as if written in the body of this License.
|
||||
|
||||
9. The Free Software Foundation may publish revised and/or new versions
|
||||
of the General Public License from time to time. Such new versions will
|
||||
be similar in spirit to the present version, but may differ in detail to
|
||||
address new problems or concerns.
|
||||
|
||||
Each version is given a distinguishing version number. If the Program
|
||||
specifies a version number of this License which applies to it and "any
|
||||
later version", you have the option of following the terms and conditions
|
||||
either of that version or of any later version published by the Free
|
||||
Software Foundation. If the Program does not specify a version number of
|
||||
this License, you may choose any version ever published by the Free Software
|
||||
Foundation.
|
||||
|
||||
10. If you wish to incorporate parts of the Program into other free
|
||||
programs whose distribution conditions are different, write to the author
|
||||
to ask for permission. For software which is copyrighted by the Free
|
||||
Software Foundation, write to the Free Software Foundation; we sometimes
|
||||
make exceptions for this. Our decision will be guided by the two goals
|
||||
of preserving the free status of all derivatives of our free software and
|
||||
of promoting the sharing and reuse of software generally.
|
||||
|
||||
NO WARRANTY
|
||||
|
||||
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
|
||||
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
|
||||
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
|
||||
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
|
||||
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
|
||||
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
|
||||
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
|
||||
REPAIR OR CORRECTION.
|
||||
|
||||
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
|
||||
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
|
||||
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
|
||||
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
|
||||
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
|
||||
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
|
||||
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
|
||||
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGES.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
How to Apply These Terms to Your New Programs
|
||||
|
||||
If you develop a new program, and you want it to be of the greatest
|
||||
possible use to the public, the best way to achieve this is to make it
|
||||
free software which everyone can redistribute and change under these terms.
|
||||
|
||||
To do so, attach the following notices to the program. It is safest
|
||||
to attach them to the start of each source file to most effectively
|
||||
convey the exclusion of warranty; and each file should have at least
|
||||
the "copyright" line and a pointer to where the full notice is found.
|
||||
|
||||
<one line to give the program's name and a brief idea of what it does.>
|
||||
Copyright (C) <year> <name of author>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along
|
||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
|
||||
Also add information on how to contact you by electronic and paper mail.
|
||||
|
||||
If the program is interactive, make it output a short notice like this
|
||||
when it starts in an interactive mode:
|
||||
|
||||
Gnomovision version 69, Copyright (C) year name of author
|
||||
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
|
||||
This is free software, and you are welcome to redistribute it
|
||||
under certain conditions; type `show c' for details.
|
||||
|
||||
The hypothetical commands `show w' and `show c' should show the appropriate
|
||||
parts of the General Public License. Of course, the commands you use may
|
||||
be called something other than `show w' and `show c'; they could even be
|
||||
mouse-clicks or menu items--whatever suits your program.
|
||||
|
||||
You should also get your employer (if you work as a programmer) or your
|
||||
school, if any, to sign a "copyright disclaimer" for the program, if
|
||||
necessary. Here is a sample; alter the names:
|
||||
|
||||
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
|
||||
`Gnomovision' (which makes passes at compilers) written by James Hacker.
|
||||
|
||||
<signature of Ty Coon>, 1 April 1989
|
||||
Ty Coon, President of Vice
|
||||
|
||||
This General Public License does not permit incorporating your program into
|
||||
proprietary programs. If your program is a subroutine library, you may
|
||||
consider it more useful to permit linking proprietary applications with the
|
||||
library. If this is what you want to do, use the GNU Lesser General
|
||||
Public License instead of this License.
|
||||
Executable
+3
@@ -0,0 +1,3 @@
|
||||
Based on https://github.com/kennu/simply-static-s3
|
||||
|
||||
Updated for modern v4 API support and generic S3 providers.
|
||||
Executable
+18
@@ -0,0 +1,18 @@
|
||||
<?php if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly
|
||||
|
||||
/**
|
||||
* Plugin Name: Simply Static S3
|
||||
* Plugin URI: https://github.com/kennu/simply-static-s3
|
||||
* Description: Produces a static HTML version of your WordPress install, adjusts URLs accordingly and deploys to Amazon S3.
|
||||
* Version: 2.0.0
|
||||
* Author: Kenneth Falck (based on Code of Conduct)
|
||||
* Author URI: https://github.com/kennu
|
||||
* License: GPL-2.0+
|
||||
* License URI: http://www.gnu.org/licenses/gpl-2.0.txt
|
||||
* Text Domain: simply-static-s3
|
||||
* Domain Path: /languages
|
||||
*/
|
||||
|
||||
require plugin_dir_path( __FILE__ ) . 'includes/class-simply-static.php';
|
||||
|
||||
Simply_Static::init( __FILE__ );
|
||||
@@ -0,0 +1,12 @@
|
||||
<?php
|
||||
/**
|
||||
* Uninstall Simply Static
|
||||
*
|
||||
* @package Simply_Static
|
||||
*/
|
||||
|
||||
// exit if accessed directly
|
||||
if ( ! defined( 'WP_UNINSTALL_PLUGIN' ) ) exit;
|
||||
|
||||
// Delete Simply Static's settings
|
||||
delete_option( 'simply-static' );
|
||||
@@ -0,0 +1,34 @@
|
||||
<?php
|
||||
/**
|
||||
* @package Simply_Static
|
||||
*/
|
||||
?>
|
||||
|
||||
<h2><?php _e( 'Simply Static S3', $this->slug ); ?></h2>
|
||||
|
||||
<div class="wrap">
|
||||
|
||||
<?php if ( is_array( $this->export_log ) && count( $this->export_log ) ): ?>
|
||||
<h3><?php _e( 'Export Log', $this->slug ); ?></h3>
|
||||
<div class="export-log">
|
||||
<pre><?php echo implode( "\n", $this->export_log ) ?></pre>
|
||||
</div>
|
||||
<?php endif ?>
|
||||
|
||||
<form id="generate" method="post" action="">
|
||||
|
||||
<?php if ( $this->system_requirements_check_failed ) : ?>
|
||||
<p><?php _e( "Uh oh, we've found an issue that prevents us from creating a static copy of your site.", $this->slug ); ?></p>
|
||||
<?php else : ?>
|
||||
<p><?php _e( "Press the button below to create a static copy of your site.", $this->slug ); ?></p>
|
||||
<p><?php _e( "Note: on large sites this process may take a while.", $this->slug ); ?></p>
|
||||
<?php endif; ?>
|
||||
|
||||
<p class="submit">
|
||||
<?php wp_nonce_field( $this->slug ) ?>
|
||||
<input class="button button-primary button-hero" type="submit" name="generate" value="Generate Static Files" <?php if ( $this->system_requirements_check_failed ) { echo 'disabled=disabled'; } ?> />
|
||||
</p>
|
||||
|
||||
</form>
|
||||
|
||||
</div>
|
||||
@@ -0,0 +1,54 @@
|
||||
<?php
|
||||
/**
|
||||
* @package Simply_Static
|
||||
*/
|
||||
?>
|
||||
|
||||
<?php foreach ( $this->flashes as $flash ) : ?>
|
||||
<div class="fade <?php echo $flash['type']; ?>">
|
||||
<p><strong>
|
||||
<?php echo $flash['message']; ?>
|
||||
</strong></p>
|
||||
</div>
|
||||
<?php endforeach; ?>
|
||||
|
||||
<div class="wrap">
|
||||
<div id="sistContainer">
|
||||
|
||||
<div id="sistContent">
|
||||
<?php include $this->template; ?>
|
||||
</div>
|
||||
<!-- .sist-content -->
|
||||
|
||||
<div id="sistSidebar">
|
||||
<div class="sidebar-container metabox-holder">
|
||||
<div class="postbox">
|
||||
<h3 class="wp-ui-primary"><?php _e( 'Like this plugin?', $this->slug ); ?></h3>
|
||||
<div class="inside">
|
||||
<div class="main">
|
||||
<p><?php _e( 'Join the mailing list to be notified when new features and plugins are released.', $this->slug ); ?></p>
|
||||
|
||||
<!-- Begin MailChimp Signup Form -->
|
||||
<div id="mc_embed_signup">
|
||||
<form action="//codeofconduct.us8.list-manage.com/subscribe/post?u=add8381918934d53034b89daf&id=7b053181a2" method="post" id="mc-embedded-subscribe-form" name="mc-embedded-subscribe-form" class="validate" target="_blank" novalidate>
|
||||
<div id="mc_embed_signup_scroll">
|
||||
<input type="email" value="" name="EMAIL" class="email" id="mce-EMAIL" placeholder="<?php _e( 'email address', $this->slug ); ?>" required>
|
||||
<!-- real people should not fill this in and expect good things - do not remove this or risk form bot signups-->
|
||||
<div style="position: absolute; left: -5000px;"><input type="text" name="b_add8381918934d53034b89daf_7b053181a2" tabindex="-1" value=""></div>
|
||||
<div class="clear"><input type="submit" value="<?php _e( 'Subscribe', $this->slug ); ?>" name="subscribe" id="mc-embedded-subscribe" class="button-primary"></div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
<!--End mc_embed_signup-->
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- .sist-sidebar -->
|
||||
|
||||
</div>
|
||||
<!-- .sist-container -->
|
||||
</div>
|
||||
<!-- .wrap -->
|
||||
@@ -0,0 +1,200 @@
|
||||
<?php
|
||||
/**
|
||||
* @package Simply_Static
|
||||
*/
|
||||
?>
|
||||
|
||||
<div class='wrap'>
|
||||
|
||||
<h2><?php _e( 'Simply Static S3', $this->slug ); ?></h2>
|
||||
|
||||
<form id='options' method='post' action=''>
|
||||
|
||||
<?php wp_nonce_field( $this->slug ) ?>
|
||||
|
||||
<h2 id='sistTabs' class='nav-tab-wrapper'>
|
||||
<a class='nav-tab' id='general-tab' href='#tab-general'><?php _e( 'General', $this->slug ); ?></a>
|
||||
<a class='nav-tab' id='advanced-tab' href='#tab-advanced'><?php _e( 'Advanced', $this->slug ); ?></a>
|
||||
</h2>
|
||||
|
||||
<div id='general' class='tab-pane'>
|
||||
|
||||
<table class='form-table'>
|
||||
<tbody>
|
||||
<tr>
|
||||
<th>
|
||||
<label for='originHost'><?php _e( "Origin URL", $this->slug );?></label>
|
||||
</th>
|
||||
<td>
|
||||
<select id='originScheme' name='origin_scheme' disabled>
|
||||
<option value='<?php echo $this->origin_scheme; ?>'><?php echo $this->origin_scheme; ?>://</option>
|
||||
</select>
|
||||
<input aria-describedby='originHostHelpBlock' type='text' id='originHost' name='origin_host' value='<?php echo esc_attr( $this->origin_host ) ?>' size='50' disabled />
|
||||
<p id='originHostHelpBlock' class='help-block'><?php echo sprintf( __( "This is the URL of your WordPress installation. You can edit the URL on <a href='%s'>the General Settings page</a>.", $this->slug ), admin_url( '/options-general.php' ) ); ?></p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>
|
||||
<label for='destinationHost'><?php _e( "Destination URL", $this->slug );?></label>
|
||||
</th>
|
||||
<td>
|
||||
<select id='destinationScheme' name='destination_scheme'>
|
||||
<option value='http' <?php sist_selected_if( $this->destination_scheme == 'http' ) ?>>http://</option>
|
||||
<option value='https' <?php sist_selected_if( $this->destination_scheme == 'https' ) ?>>https://</option>
|
||||
</select>
|
||||
<input aria-describedby='destinationHostHelpBlock' type='text' id='destinationHost' name='destination_host' value='<?php echo esc_attr( $this->destination_host ) ?>' size='50' />
|
||||
<p id='destinationHostHelpBlock' class='help-block'><?php _e( "This is the URL where your static site will live. When generating your static site, all links to the Origin URL will be replaced with the Destination URL.", $this->slug ); ?></p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>
|
||||
<label for='deliveryMethod'><?php _e( "Delivery Method", $this->slug ); ?></label></th>
|
||||
<td>
|
||||
<select name='delivery_method' id='deliveryMethod'>
|
||||
<option value='s3' <?php sist_selected_if( $this->delivery_method == 's3' ) ?>><?php _e( "Amazon S3", $this->slug ); ?></option>
|
||||
<option value='zip' <?php sist_selected_if( $this->delivery_method == 'zip' ) ?>><?php _e( "ZIP Archive", $this->slug ); ?></option>
|
||||
<option value='local' <?php sist_selected_if( $this->delivery_method == 'local' ) ?>><?php _e( "Local Directory", $this->slug ); ?></option>
|
||||
</select>
|
||||
</td>
|
||||
</tr>
|
||||
<tr class='delivery-method zip'>
|
||||
<th></th>
|
||||
<td>
|
||||
<p><?php _e( "Saving your static files to a ZIP archive is Simply Static's default delivery method. After generating your static files you will be prompted to download the ZIP archive.", $this->slug ); ?></p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr class='delivery-method local'>
|
||||
<th></th>
|
||||
<td>
|
||||
<p><?php _e( "Saving your static files to a local directory is useful if you want to serve your static files from the same server as your WordPress installation. WordPress can live on a subdomain (e.g. wordpress.example.com) while your static files are served from your primary domain (e.g. www.example.com).", $this->slug ); ?></p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr class='delivery-method local'>
|
||||
<th>
|
||||
<label for='local_dir'><?php _e( "Local Directory", $this->slug );?></label>
|
||||
</th>
|
||||
<td>
|
||||
<?php $example_local_dir = plugin_dir_path( dirname( __FILE__ ) ); ?>
|
||||
<input aria-describedby='localDirHelpBlock' type='text' id='localDir' name='local_dir' value='<?php echo esc_attr( $this->local_dir ) ?>' placeholder='<?php echo $example_local_dir; ?>' class='widefat' />
|
||||
<p id='localDirHelpBlock' class='help-block'><?php _e( "This is the directory where your static files will be saved. The directory must exist and be writeable by the webserver.", $this->slug ); ?></p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr class='delivery-method s3'>
|
||||
<th></th>
|
||||
<td>
|
||||
<p><?php _e( "A static copy of your site will be published to Amazon S3 in the bucket you specify.", $this->slug ); ?></p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr class='delivery-method s3'>
|
||||
<th>
|
||||
<label for='aws_s3_bucket'><?php _e( "AWS S3 Bucket", $this->slug );?></label>
|
||||
</th>
|
||||
<td>
|
||||
<input aria-describedby='awsS3BucketHelpBlock' type='text' id='awsS3Bucket' name='aws_s3_bucket' value='<?php echo esc_attr( $this->aws_s3_bucket ) ?>' placeholder='Existing bucket name' class='widefat' />
|
||||
<p id='awsS3BucketHelpBlock' class='help-block'><?php _e( "Your static site will be published in this S3 bucket. It must already exist. Use AWS Console to create a bucket.", $this->slug ); ?></p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr class='delivery-method s3'>
|
||||
<th>
|
||||
<label for='aws_access_key_id'><?php _e( "AWS Access Key ID", $this->slug );?></label>
|
||||
</th>
|
||||
<td>
|
||||
<input aria-describedby='awsAccessKeyIDHelpBlock' type='text' id='awsS3AccessKeyID' name='aws_access_key_id' value='<?php echo esc_attr( $this->aws_access_key_id ) ?>' placeholder='Access Key ID with write access to S3' class='widefat' />
|
||||
<p id='awsS3AccessKeyIDHelpBlock' class='help-block'><?php _e( "If you don't have an access key, use AWS Console IAM to generate a new user and access key. It must have rights to publish to S3.", $this->slug ); ?></p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr class='delivery-method s3'>
|
||||
<th>
|
||||
<label for='aws_secret_access_key'><?php _e( "AWS Secret Access Key", $this->slug );?></label>
|
||||
</th>
|
||||
<td>
|
||||
<input aria-describedby='awsSecretAccessKeyHelpBlock' type='text' id='awsSecretS3AccessKey' name='aws_secret_access_key' value='<?php echo esc_attr( $this->aws_secret_access_key ) ?>' placeholder='Secret Access Key with write access to S3' class='widefat' />
|
||||
<p id='awsS3SecretAccessKeyHelpBlock' class='help-block'><?php _e( "If you don't have an access key, use AWS Console IAM to generate a new user and access key. It must have rights to publish to S3.", $this->slug ); ?></p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr class='delivery-method s3'>
|
||||
<th>
|
||||
<label for='aws_s3_region'><?php _e( "S3 Region", $this->slug );?></label>
|
||||
</th>
|
||||
<td>
|
||||
<input aria-describedby='awsS3RegionHelpBlock' type='text' id='awsS3Region' name='aws_s3_region' value='<?php echo esc_attr( $this->aws_s3_region ) ?>' placeholder='us-east-1' class='widefat' />
|
||||
<p id='awsS3RegionHelpBlock' class='help-block'><?php _e( "The region of your S3 bucket (e.g. us-east-1, eu-west-1, us-west-1).", $this->slug ); ?></p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr class='delivery-method s3'>
|
||||
<th>
|
||||
<label for='aws_s3_endpoint'><?php _e( "S3 Endpoint URL", $this->slug );?></label>
|
||||
</th>
|
||||
<td>
|
||||
<input aria-describedby='awsS3EndpointHelpBlock' type='text' id='awsS3Endpoint' name='aws_s3_endpoint' value='<?php echo esc_attr( $this->aws_s3_endpoint ) ?>' placeholder='s3.amazonaws.com' class='widefat' />
|
||||
<p id='awsS3EndpointHelpBlock' class='help-block'><?php _e( "The endpoint URL for your S3 provider (e.g. s3.amazonaws.com, s3.wasabisys.com, s3.us-west-002.backblazeb2.com).", $this->slug ); ?></p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th></th>
|
||||
<td>
|
||||
<p class='submit'>
|
||||
<input class='button button-primary' type='submit' name='save' value='<?php _e( "Save Changes", $this->slug );?>' />
|
||||
</p>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<div id='advanced' class='tab-pane'>
|
||||
|
||||
<table class='form-table'>
|
||||
<tbody>
|
||||
<tr>
|
||||
<th>
|
||||
<label for='tempFilesDir'><?php _e( "Temporary Files Directory", $this->slug );?></label>
|
||||
</th>
|
||||
<td>
|
||||
<?php $example_temp_files_dir = trailingslashit( plugin_dir_path( dirname( __FILE__ ) ) . 'static-files' );?>
|
||||
<input aria-describedby='tempFilesDirHelpBlock' type='text' id='tempFilesDir' name='temp_files_dir' value='<?php echo esc_attr( $this->temp_files_dir ) ?>' placeholder='<?php echo $example_temp_files_dir; ?>'class='widefat' />
|
||||
<p id='tempFilesDirHelpBlock' class='help-block'><?php _e( "Your static files (and ZIP archives, if generated) are temporarily saved to this directory. This directory must exist and be writeable.", $this->slug ); ?></p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th></th>
|
||||
<td>
|
||||
<label>
|
||||
<input aria-describedby='deleteTempFilesHelpBlock' name='delete_temp_files' id='deleteTempFiles' value='1' type='checkbox' <?php if ( $this->delete_temp_files == '1' ) { echo 'checked'; } ?> />
|
||||
<?php _e( "Delete temporary files", $this->slug ); ?>
|
||||
</label>
|
||||
<p id='deleteTempFilesHelpBlock' class='help-block'>
|
||||
<?php _e( "Static files are temporarily saved to the directory above before being copied to their destination. These files can be deleted after the copy process, or you can keep them as a backup.", $this->slug ); ?>
|
||||
</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>
|
||||
<label for='additionalUrls'><?php _e( "Additional URLs", $this->slug );?></label>
|
||||
</th>
|
||||
<td>
|
||||
<textarea aria-describedby='additionalUrlsHelpBlock' class='widefat' name='additional_urls' id='additionalUrls' rows='5' cols='10'><?php echo esc_html( $this->additional_urls ) ?></textarea>
|
||||
<p id='additionalUrlsHelpBlock' class='help-block'>
|
||||
<?php echo sprintf( __( "Simply Static will create a static copy of any page it can find a link to, starting at %s. If you want to create static copies of pages or files that <em>aren't</em> linked to, add the URLs here (one per line). Examples: <code>%s</code> or <code>%s</code>", $this->slug),
|
||||
$this->origin_scheme . '://' . $this->origin_host,
|
||||
$this->origin_scheme . '://' . $this->origin_host . '/hidden-page',
|
||||
$this->origin_scheme . '://' . $this->origin_host . '/images/secret.jpg' ); ?>
|
||||
</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th></th>
|
||||
<td>
|
||||
<p class='submit'>
|
||||
<input class='button button-primary' type='submit' name='save' value='<?php _e( "Save Changes", $this->slug );?>' />
|
||||
</p>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
</div>
|
||||
|
||||
</form>
|
||||
|
||||
</div>
|
||||
@@ -0,0 +1,16 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title><?php _e( 'Redirecting...', $this->slug ); ?></title>
|
||||
<noscript>
|
||||
<meta http-equiv="refresh" content="0;url=<?php echo $this->redirect_url; ?>">
|
||||
</noscript>
|
||||
|
||||
<script type="text/javascript">
|
||||
window.location = "<?php echo $this->redirect_url; ?>";
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
<p>You are being redirected to <a href="<?php echo $this->redirect_url; ?>"><?php echo $this->redirect_url; ?></a></p>
|
||||
</body>
|
||||
</html>
|
||||
Reference in new issue
Block a user