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 .= ' ' . __( 'Click here to download', self::SLUG ) . ''; $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 the Permalink Settings page.", 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 the PHP zip extension page 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; } }