From 905cd2810f368e4a7e902b4d48418cbaf0458f37 Mon Sep 17 00:00:00 2001 From: Derek Herman Date: Wed, 4 Feb 2015 17:03:02 -0800 Subject: [PATCH 01/10] tested in 4.1 --- index.php | 2 +- readme.txt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/index.php b/index.php index 01b4f3d..262575e 100644 --- a/index.php +++ b/index.php @@ -661,7 +661,7 @@ protected function _admin_update_check() { 'zip_url' => 'https://github.com/envato/' . EWPT_PLUGIN_SLUG . '/archive/master.zip', 'sslverify' => true, 'requires' => '3.6', - 'tested' => '3.9.1', + 'tested' => '4.1', 'readme' => 'readme.txt', 'access_token' => '', ); diff --git a/readme.txt b/readme.txt index cf16b5e..247b77c 100644 --- a/readme.txt +++ b/readme.txt @@ -2,7 +2,7 @@ Contributors: envato, valendesigns Tags: install, update, api, envato, theme, upgrade Requires at least: 3.6 -Tested up to: 4.0.1 +Tested up to: 4.1 Stable tag: 1.7.1 WordPress toolkit for Envato Marketplace hosted items. Currently supports the following theme functionality: install, upgrade, & backups during upgrade. From 0482a7007379b25084d5ba6f864e99fb0d94e1a0 Mon Sep 17 00:00:00 2001 From: Derek Herman Date: Wed, 4 Feb 2015 17:03:49 -0800 Subject: [PATCH 02/10] version bump --- index.php | 4 ++-- readme.txt | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/index.php b/index.php index 262575e..d006e4b 100644 --- a/index.php +++ b/index.php @@ -3,7 +3,7 @@ * Plugin Name: Envato WordPress Toolkit * Plugin URI: https://github.com/envato/envato-wordpress-toolkit * Description: WordPress toolkit for Envato Marketplace hosted items. Currently supports the following theme functionality: install, upgrade, & backups during upgrade. - * Version: 1.7.1 + * Version: 1.7.2 * Author: Envato * Author URI: http://envato.com */ @@ -60,7 +60,7 @@ protected function _constants() { /** * Plugin Version */ - define( 'EWPT_PLUGIN_VER', '1.7.1' ); + define( 'EWPT_PLUGIN_VER', '1.7.2' ); /** * Plugin Name diff --git a/readme.txt b/readme.txt index 247b77c..505ef7b 100644 --- a/readme.txt +++ b/readme.txt @@ -3,7 +3,7 @@ Contributors: envato, valendesigns Tags: install, update, api, envato, theme, upgrade Requires at least: 3.6 Tested up to: 4.1 -Stable tag: 1.7.1 +Stable tag: 1.7.2 WordPress toolkit for Envato Marketplace hosted items. Currently supports the following theme functionality: install, upgrade, & backups during upgrade. From 7266725c3d7ebf1aca2a29aca93165726fd81456 Mon Sep 17 00:00:00 2001 From: Derek Herman Date: Thu, 12 Feb 2015 14:32:11 -0800 Subject: [PATCH 03/10] stop redeclare class errors --- includes/class-envato-api.php | 716 +++++----- includes/class-envato-backup.php | 1597 +++++++++++----------- index.php | 2114 +++++++++++++++--------------- readme.txt | 3 + 4 files changed, 2225 insertions(+), 2205 deletions(-) diff --git a/includes/class-envato-api.php b/includes/class-envato-api.php index a16fac8..2870e23 100644 --- a/includes/class-envato-api.php +++ b/includes/class-envato-api.php @@ -9,397 +9,401 @@ * @subpackage Envato WordPress Toolkit * @author Derek Herman * @since 1.0 - */ -class Envato_Protected_API { - /** - * The buyer's Username - * - * @var string - * - * @access public - * @since 1.0 - */ - public $user_name; - - /** - * The buyer's API Key - * - * @var string - * - * @access public - * @since 1.0 - */ - public $api_key; - - /** - * The default API URL - * - * @var string - * - * @access private - * @since 1.0 - */ - protected $public_url = 'http://marketplace.envato.com/api/edge/set.json'; - - /** - * Error messages - * - * @var array - * - * @access public - * @since 1.0 - */ - public $errors = array( 'errors' => '' ); - - /** - * Class contructor method - * - * @param string The buyer's Username - * @param string The buyer's API Key can be accessed on the marketplaces via My Account -> My Settings -> API Key - * @return void Sets error messages if any. - * - * @access public - * @since 1.0 - */ - public function __construct( $user_name = '', $api_key = '' ) { - - if ( $user_name == '' ) { - $this->set_error( 'user_name', __( 'Please enter your Envato Marketplace Username.', 'envato-wordpress-toolkit' ) ); - } + */ +if ( ! class_exists( 'Envato_Protected_API' ) ) { + + class Envato_Protected_API { + /** + * The buyer's Username + * + * @var string + * + * @access public + * @since 1.0 + */ + public $user_name; + + /** + * The buyer's API Key + * + * @var string + * + * @access public + * @since 1.0 + */ + public $api_key; + + /** + * The default API URL + * + * @var string + * + * @access private + * @since 1.0 + */ + protected $public_url = 'http://marketplace.envato.com/api/edge/set.json'; + + /** + * Error messages + * + * @var array + * + * @access public + * @since 1.0 + */ + public $errors = array( 'errors' => '' ); + + /** + * Class contructor method + * + * @param string The buyer's Username + * @param string The buyer's API Key can be accessed on the marketplaces via My Account -> My Settings -> API Key + * @return void Sets error messages if any. + * + * @access public + * @since 1.0 + */ + public function __construct( $user_name = '', $api_key = '' ) { + + if ( $user_name == '' ) { + $this->set_error( 'user_name', __( 'Please enter your Envato Marketplace Username.', 'envato-wordpress-toolkit' ) ); + } + + if ( $api_key == '' ) { + $this->set_error( 'api_key', __( 'Please enter your Envato Marketplace API Key.', 'envato-wordpress-toolkit' ) ); + } + + $this->user_name = $user_name; + $this->api_key = $api_key; - if ( $api_key == '' ) { - $this->set_error( 'api_key', __( 'Please enter your Envato Marketplace API Key.', 'envato-wordpress-toolkit' ) ); } - - $this->user_name = $user_name; - $this->api_key = $api_key; - } - - /** - * Get private user data. - * - * @param string Available sets: 'vitals', 'earnings-and-sales-by-month', 'statement', 'recent-sales', 'account', 'verify-purchase', 'download-purchase', 'wp-list-themes', 'wp-download' - * @param string The buyer/author username to test against. - * @param string Additional set data such as purchase code or item id. - * @param bool Allow API calls to be cached. Default false. - * @param int Set transient timeout. Default 300 seconds (5 minutes). - * @return array An array of values (possibly cached) from the requested set, or an error message. - * - * @access public - * @since 1.0 - * @updated 1.3 - */ - public function private_user_data( $set = '', $user_name = '', $set_data = '', $allow_cache = false, $timeout = 300 ) { - - if ( $set == '' ) { - $this->set_error( 'set', __( 'The API "set" is a required parameter.', 'envato-wordpress-toolkit' ) ); - } + /** + * Get private user data. + * + * @param string Available sets: 'vitals', 'earnings-and-sales-by-month', 'statement', 'recent-sales', 'account', 'verify-purchase', 'download-purchase', 'wp-list-themes', 'wp-download' + * @param string The buyer/author username to test against. + * @param string Additional set data such as purchase code or item id. + * @param bool Allow API calls to be cached. Default false. + * @param int Set transient timeout. Default 300 seconds (5 minutes). + * @return array An array of values (possibly cached) from the requested set, or an error message. + * + * @access public + * @since 1.0 + * @updated 1.3 + */ + public function private_user_data( $set = '', $user_name = '', $set_data = '', $allow_cache = false, $timeout = 300 ) { - if ( $user_name == '' ) { - $user_name = $this->user_name; - } - - if ( $user_name == '' ) { - $this->set_error( 'user_name', __( 'Please enter your Envato Marketplace Username.', 'envato-wordpress-toolkit' ) ); - } + if ( $set == '' ) { + $this->set_error( 'set', __( 'The API "set" is a required parameter.', 'envato-wordpress-toolkit' ) ); + } + + if ( $user_name == '' ) { + $user_name = $this->user_name; + } - if ( $set_data !== '' ) { - $set_data = ":$set_data"; - } - - if ( $errors = $this->api_errors() ) { - return $errors; - } + if ( $user_name == '' ) { + $this->set_error( 'user_name', __( 'Please enter your Envato Marketplace Username.', 'envato-wordpress-toolkit' ) ); + } + + if ( $set_data !== '' ) { + $set_data = ":$set_data"; + } + + if ( $errors = $this->api_errors() ) { + return $errors; + } + + $url = "http://marketplace.envato.com/api/edge/$user_name/$this->api_key/$set$set_data.json"; + + /* set transient ID for later */ + $transient = substr( md5( $user_name . '_' . $set . $set_data ), 0, 16 ); + + if ( $allow_cache ) { + $cache_results = $this->set_cache( $transient, $url, $timeout ); + $results = $cache_results; + } else { + $results = $this->remote_request( $url ); + } + + if ( isset( $results->error ) ) { + $this->set_error( 'error_' . $set, $results->error ); + } + + if ( $errors = $this->api_errors() ) { + $this->clear_cache( $transient ); + return $errors; + } + + if ( isset( $results->$set ) ) { + return $results->$set; + } + + return false; - $url = "http://marketplace.envato.com/api/edge/$user_name/$this->api_key/$set$set_data.json"; - - /* set transient ID for later */ - $transient = substr( md5( $user_name . '_' . $set . $set_data ), 0, 16 ); - - if ( $allow_cache ) { - $cache_results = $this->set_cache( $transient, $url, $timeout ); - $results = $cache_results; - } else { - $results = $this->remote_request( $url ); - } - - if ( isset( $results->error ) ) { - $this->set_error( 'error_' . $set, $results->error ); - } - - if ( $errors = $this->api_errors() ) { - $this->clear_cache( $transient ); - return $errors; - } - - if ( isset( $results->$set ) ) { - return $results->$set; - } - - return false; - - } - - /** - * Used to list purchased themes. - * - * @param bool Allow API calls to be cached. Default true. - * @param int Set transient timeout. Default 300 seconds (5 minutes). - * @return object If user has purchased themes, returns an object containing those details. - * - * @access public - * @since 1.0 - * @updated 1.3 - */ - public function wp_list_themes( $allow_cache = true, $timeout = 300 ) { - - if ( $this->user_name == '' ) { - $this->set_error( 'user_name', __( 'Please enter your Envato Marketplace Username.', 'envato-wordpress-toolkit' ) ); } - $themes = $this->private_user_data( 'wp-list-themes', $this->user_name, '', $allow_cache, $timeout ); - - if ( $errors = $this->api_errors() ) { - return $errors; + /** + * Used to list purchased themes. + * + * @param bool Allow API calls to be cached. Default true. + * @param int Set transient timeout. Default 300 seconds (5 minutes). + * @return object If user has purchased themes, returns an object containing those details. + * + * @access public + * @since 1.0 + * @updated 1.3 + */ + public function wp_list_themes( $allow_cache = true, $timeout = 300 ) { + + if ( $this->user_name == '' ) { + $this->set_error( 'user_name', __( 'Please enter your Envato Marketplace Username.', 'envato-wordpress-toolkit' ) ); + } + + $themes = $this->private_user_data( 'wp-list-themes', $this->user_name, '', $allow_cache, $timeout ); + + if ( $errors = $this->api_errors() ) { + return $errors; + } + + return $themes; + } - return $themes; - - } - - /** - * Used to download a purchased item. - * - * This method does not allow caching. - * - * @param string The purchased items id - * @return string|bool If item purchased, returns the download URL. - * - * @access public - * @since 1.0 - */ - public function wp_download( $item_id ) { - - if ( ! isset( $item_id ) ) { - $this->set_error( 'item_id', __( 'The Envato Marketplace "item ID" is a required parameter.', 'envato-wordpress-toolkit' ) ); - } + /** + * Used to download a purchased item. + * + * This method does not allow caching. + * + * @param string The purchased items id + * @return string|bool If item purchased, returns the download URL. + * + * @access public + * @since 1.0 + */ + public function wp_download( $item_id ) { - $download = $this->private_user_data( 'wp-download', $this->user_name, $item_id ); - - if ( $errors = $this->api_errors() ) { - return $errors; - } else if ( isset( $download->url ) ) { - return $download->url; + if ( ! isset( $item_id ) ) { + $this->set_error( 'item_id', __( 'The Envato Marketplace "item ID" is a required parameter.', 'envato-wordpress-toolkit' ) ); + } + + $download = $this->private_user_data( 'wp-download', $this->user_name, $item_id ); + + if ( $errors = $this->api_errors() ) { + return $errors; + } else if ( isset( $download->url ) ) { + return $download->url; + } + + return false; } - return false; - } - - /** - * Retrieve the details for a specific marketplace item. - * - * @param string $item_id The id of the item you need information for. - * @return object Details for the given item. - * - * @access public - * @since 1.0 - * @updated 1.3 - */ - public function item_details( $item_id, $allow_cache = true, $timeout = 300 ) { - - $url = preg_replace( '/set/i', 'item:' . $item_id, $this->public_url ); - - /* set transient ID for later */ - $transient = substr( md5( 'item_' . $item_id ), 0, 16 ); - - if ( $allow_cache ) { - $cache_results = $this->set_cache( $transient, $url, $timeout ); - $results = $cache_results; - } else { - $results = $this->remote_request( $url ); + /** + * Retrieve the details for a specific marketplace item. + * + * @param string $item_id The id of the item you need information for. + * @return object Details for the given item. + * + * @access public + * @since 1.0 + * @updated 1.3 + */ + public function item_details( $item_id, $allow_cache = true, $timeout = 300 ) { + + $url = preg_replace( '/set/i', 'item:' . $item_id, $this->public_url ); + + /* set transient ID for later */ + $transient = substr( md5( 'item_' . $item_id ), 0, 16 ); + + if ( $allow_cache ) { + $cache_results = $this->set_cache( $transient, $url, $timeout ); + $results = $cache_results; + } else { + $results = $this->remote_request( $url ); + } + + if ( isset( $results->error ) ) { + $this->set_error( 'error_item_' . $item_id, $results->error ); + } + + if ( $errors = $this->api_errors() ) { + $this->clear_cache( $transient ); + return $errors; + } + + if ( isset( $results->item ) ) { + return $results->item; + } + + return false; + } - if ( isset( $results->error ) ) { - $this->set_error( 'error_item_' . $item_id, $results->error ); + /** + * Set cache with the Transients API. + * + * @link http://codex.wordpress.org/Transients_API + * + * @param string Transient ID. + * @param string The URL of the API request. + * @param int Set transient timeout. Default 300 seconds (5 minutes). + * @return mixed + * + * @access public + * @since 1.3 + */ + public function set_cache( $transient = '', $url = '', $timeout = 300 ) { + + if ( $transient == '' || $url == '' ) { + return false; + } + + /* keep the code below cleaner */ + $transient = $this->validate_transient( $transient ); + $transient_timeout = '_transient_timeout_' . $transient; + + /* set original cache before we destroy it */ + $old_cache = get_option( $transient_timeout ) < time() ? get_option( $transient ) : ''; + + /* look for a cached result and return if exists */ + if ( false !== $results = get_transient( $transient ) ) { + return $results; + } + + /* create the cache and allow filtering before it's saved */ + if ( $results = apply_filters( 'envato_api_set_cache', $this->remote_request( $url ), $transient ) ) { + set_transient( $transient, $results, $timeout ); + return $results; + } + + return false; + } - if ( $errors = $this->api_errors() ) { - $this->clear_cache( $transient ); - return $errors; - } + /** + * Clear cache with the Transients API. + * + * @link http://codex.wordpress.org/Transients_API + * + * @param string Transient ID. + * @return void + * + * @access public + * @since 1.3 + */ + public function clear_cache( $transient = '' ) { + + delete_transient( $transient ); - if ( isset( $results->item ) ) { - return $results->item; } - return false; - - } - - /** - * Set cache with the Transients API. - * - * @link http://codex.wordpress.org/Transients_API - * - * @param string Transient ID. - * @param string The URL of the API request. - * @param int Set transient timeout. Default 300 seconds (5 minutes). - * @return mixed - * - * @access public - * @since 1.3 - */ - public function set_cache( $transient = '', $url = '', $timeout = 300 ) { + /** + * Helper function to validate transient ID's. + * + * @param string The transient ID. + * @return string Returns a DB safe transient ID. + * + * @access public + * @since 1.3 + */ + public function validate_transient( $id = '' ) { - if ( $transient == '' || $url == '' ) { - return false; - } - - /* keep the code below cleaner */ - $transient = $this->validate_transient( $transient ); - $transient_timeout = '_transient_timeout_' . $transient; - - /* set original cache before we destroy it */ - $old_cache = get_option( $transient_timeout ) < time() ? get_option( $transient ) : ''; - - /* look for a cached result and return if exists */ - if ( false !== $results = get_transient( $transient ) ) { - return $results; + return preg_replace( '/[^A-Za-z0-9\_\-]/i', '', str_replace( ':', '_', $id ) ); + } - /* create the cache and allow filtering before it's saved */ - if ( $results = apply_filters( 'envato_api_set_cache', $this->remote_request( $url ), $transient ) ) { - set_transient( $transient, $results, $timeout ); - return $results; + /** + * Helper function to set error messages. + * + * @param string The error array id. + * @param string The error message. + * @return void + * + * @access public + * @since 1.0 + */ + public function set_error( $id, $error ) { + + $this->errors['errors'][$id] = $error; + } - return false; - - } - - /** - * Clear cache with the Transients API. - * - * @link http://codex.wordpress.org/Transients_API - * - * @param string Transient ID. - * @return void - * - * @access public - * @since 1.3 - */ - public function clear_cache( $transient = '' ) { - - delete_transient( $transient ); - - } - - /** - * Helper function to validate transient ID's. - * - * @param string The transient ID. - * @return string Returns a DB safe transient ID. - * - * @access public - * @since 1.3 - */ - public function validate_transient( $id = '' ) { - - return preg_replace( '/[^A-Za-z0-9\_\-]/i', '', str_replace( ':', '_', $id ) ); - - } - - /** - * Helper function to set error messages. - * - * @param string The error array id. - * @param string The error message. - * @return void - * - * @access public - * @since 1.0 - */ - public function set_error( $id, $error ) { - - $this->errors['errors'][$id] = $error; - - } - - /** - * Helper function to return the set errors. - * - * @return array The errors array. - * - * @access public - * @since 1.0 - */ - public function api_errors() { - - if ( ! empty( $this->errors['errors'] ) ) { - return $this->errors['errors']; + /** + * Helper function to return the set errors. + * + * @return array The errors array. + * + * @access public + * @since 1.0 + */ + public function api_errors() { + + if ( ! empty( $this->errors['errors'] ) ) { + return $this->errors['errors']; + } + } - } + /** + * Helper function to query the marketplace API via wp_remote_request. + * + * @param string The url to access. + * @return object The results of the wp_remote_request request. + * + * @access private + * @since 1.0 + */ + protected function remote_request( $url ) { + + if ( empty( $url ) ) { + return false; + } + + $args = array( + 'headers' => array( 'Accept-Encoding' => '' ), + 'sslverify' => false, + 'timeout' => 300 + ); + $request = wp_remote_request( $url, $args ); - /** - * Helper function to query the marketplace API via wp_remote_request. - * - * @param string The url to access. - * @return object The results of the wp_remote_request request. - * - * @access private - * @since 1.0 - */ - protected function remote_request( $url ) { + if ( is_wp_error( $request ) ) { + echo $request->get_error_message(); + return false; + } - if ( empty( $url ) ) { + $data = json_decode( $request['body'] ); + + if ( $request['response']['code'] == 200 ) { + return $data; + } else { + $this->set_error( 'http_code', $request['response']['code'] ); + } + + if ( isset( $data->error ) ) { + $this->set_error( 'api_error', $data->error ); + } + return false; } - $args = array( - 'headers' => array( 'Accept-Encoding' => '' ), - 'sslverify' => false, - 'timeout' => 300 - ); - $request = wp_remote_request( $url, $args ); - - if ( is_wp_error( $request ) ) { - echo $request->get_error_message(); - return false; - } - - $data = json_decode( $request['body'] ); - - if ( $request['response']['code'] == 200 ) { - return $data; - } else { - $this->set_error( 'http_code', $request['response']['code'] ); - } + /** + * Helper function to print arrays to the screen ofr testing. + * + * @param array The array to print out + * @return string + * + * @access public + * @since 1.0 + */ + public function pretty_print( $array ) { + + echo '
';
+      print_r( $array );
+      echo '
'; - if ( isset( $data->error ) ) { - $this->set_error( 'api_error', $data->error ); } - - return false; - } - - /** - * Helper function to print arrays to the screen ofr testing. - * - * @param array The array to print out - * @return string - * - * @access public - * @since 1.0 - */ - public function pretty_print( $array ) { - - echo '
';
-    print_r( $array );
-    echo '
'; - } + } /* End of file class-envato-api.php */ diff --git a/includes/class-envato-backup.php b/includes/class-envato-backup.php index ca35ff3..815eca6 100644 --- a/includes/class-envato-backup.php +++ b/includes/class-envato-backup.php @@ -10,882 +10,887 @@ * @subpackage Envato WordPress Toolkit * @author Derek Herman , Human Made Limited * @since 1.4 - */ -class Envato_Backup { - /** - * The path where the backup file should be saved - * - * @access public - * @since 1.4 - * - * @var string - */ - public $path; - - /** - * The filename of the backup file - * - * @access public - * @since 1.4 - * - * @var string - */ - public $archive_filename; - - /** - * The path to the zip command - * - * @access public - * @since 1.4 - * - * @var string - */ - public $zip_command_path; - - /** - * An array of exclude rules - * - * @access public - * @since 1.4 - * - * @var array - */ - public $excludes; - - /** - * The path that should be backed up - * - * @access public - * @since 1.4 - * - * @var string - */ - public $root; - - /** - * Store the current backup instance - * - * @access public - * @since 1.4 - * - * @var object - * @static - */ - private static $instance; - - /** - * An array of all the files in root - * excluding excludes - * - * @access private - * @since 1.4 - * - * @var array - */ - private $files; - - /** - * Contains an array of error - * - * @access private - * @since 1.4 - * - * @var mixed - */ - private $errors; - - /** - * Contains an array of warnings - * - * @access private - * @since 1.4 - * - * @var mixed - */ - private $warnings; - - /** - * The archive method used - * - * @access private - * @since 1.4 - * - * @var string - */ - private $archive_method; + */ +if ( ! class_exists( 'Envato_Backup' ) ) { - /** - * PHP5 constructor method. - * - * Sets up the default properties - * - * @access public - * @since 1.4 - * - * @return null - */ - public function __construct() { - - /* Raise the memory limit and max_execution_time time */ - @ini_set( 'memory_limit', apply_filters( 'admin_memory_limit', WP_MAX_MEMORY_LIMIT ) ); - @set_time_limit( 0 ); - - $this->errors = array(); - - set_error_handler( array( $this, 'error_handler' ) ); - - /* Defaults */ - $this->root = $this->conform_dir( ABSPATH ); - - $this->path = $this->conform_dir( WP_CONTENT_DIR . '/envato-backups' ); - - $this->archive_filename = strtolower( sanitize_file_name( get_bloginfo( 'name' ) . '.backup.' . date( 'Y-m-d-H-i-s', time() + ( current_time( 'timestamp' ) - time() ) ) . '.zip' ) ); - - $this->zip_command_path = $this->guess_zip_command_path(); + class Envato_Backup { + /** + * The path where the backup file should be saved + * + * @access public + * @since 1.4 + * + * @var string + */ + public $path; + + /** + * The filename of the backup file + * + * @access public + * @since 1.4 + * + * @var string + */ + public $archive_filename; + + /** + * The path to the zip command + * + * @access public + * @since 1.4 + * + * @var string + */ + public $zip_command_path; + + /** + * An array of exclude rules + * + * @access public + * @since 1.4 + * + * @var array + */ + public $excludes; + + /** + * The path that should be backed up + * + * @access public + * @since 1.4 + * + * @var string + */ + public $root; + + /** + * Store the current backup instance + * + * @access public + * @since 1.4 + * + * @var object + * @static + */ + private static $instance; + + /** + * An array of all the files in root + * excluding excludes + * + * @access private + * @since 1.4 + * + * @var array + */ + private $files; + + /** + * Contains an array of error + * + * @access private + * @since 1.4 + * + * @var mixed + */ + private $errors; + + /** + * Contains an array of warnings + * + * @access private + * @since 1.4 + * + * @var mixed + */ + private $warnings; + + /** + * The archive method used + * + * @access private + * @since 1.4 + * + * @var string + */ + private $archive_method; + + /** + * PHP5 constructor method. + * + * Sets up the default properties + * + * @access public + * @since 1.4 + * + * @return null + */ + public function __construct() { + + /* Raise the memory limit and max_execution_time time */ + @ini_set( 'memory_limit', apply_filters( 'admin_memory_limit', WP_MAX_MEMORY_LIMIT ) ); + @set_time_limit( 0 ); + + $this->errors = array(); + + set_error_handler( array( $this, 'error_handler' ) ); + + /* Defaults */ + $this->root = $this->conform_dir( ABSPATH ); + + $this->path = $this->conform_dir( WP_CONTENT_DIR . '/envato-backups' ); + + $this->archive_filename = strtolower( sanitize_file_name( get_bloginfo( 'name' ) . '.backup.' . date( 'Y-m-d-H-i-s', time() + ( current_time( 'timestamp' ) - time() ) ) . '.zip' ) ); + + $this->zip_command_path = $this->guess_zip_command_path(); + + } - } - - /** - * Return the current instance - * - * @access public - * @since 1.4 - * - * @static - * @return object - */ - public static function get_instance() { - - if ( empty( self::$instance ) ) - self::$instance = new Envato_Backup(); - - return self::$instance; - - } - - /** - * The full filepath to the archive file. - * - * @access public - * @since 1.4 - * - * @return string - */ - public function archive_filepath() { - return trailingslashit( $this->path() ) . $this->archive_filename(); - } - - /** - * Helper function to sanitize archive filename. - * - * @access public - * @since 1.4 - * - * @return string - */ - public function archive_filename() { - return strtolower( sanitize_file_name( remove_accents( $this->archive_filename ) ) ); - } - - /** - * Helper function to sanitize the root directory path. - * - * @access public - * @since 1.4 - * - * @return string - */ - public function root() { - return $this->conform_dir( $this->root ); - } - - /** - * Helper function to sanitize the archive directory path. - * - * @access public - * @since 1.4 - * - * @return string - */ - public function path() { - return $this->conform_dir( $this->path ); - } - - /** - * Helper function to return the archive method. - * - * @access public - * @since 1.4 - * - * @return string - */ - public function archive_method() { - return $this->archive_method; - } - - /** - * Kick off a backup - * - * @access public - * @since 1.4 - * - * @return bool - */ - public function backup() { - - do_action( 'envato_backup_started', $this ); - - /* Zip everything up */ - $this->archive(); - - do_action( 'envato_backup_complete', $this ); - - } - - /** - * Zip up all the files. - * - * Attempts to use the shell zip command, if - * thats not available then it fallsback to - * PHP ZipArchive and finally PclZip. - * - * @access public - * @since 1.4 - * - * @return null - */ - public function archive() { - - do_action( 'envato_archive_started' ); + /** + * Return the current instance + * + * @access public + * @since 1.4 + * + * @static + * @return object + */ + public static function get_instance() { - /* Do we have the path to the zip command */ - if ( $this->zip_command_path ) - $this->zip(); + if ( empty( self::$instance ) ) + self::$instance = new Envato_Backup(); - /* If not or if the shell zip failed then use ZipArchive */ - if ( empty( $this->archive_verified ) && class_exists( 'ZipArchive' ) && empty( $this->skip_zip_archive ) ) - $this->zip_archive(); + return self::$instance; - /* If ZipArchive is unavailable or one of the above failed */ - if ( empty( $this->archive_verified ) ) - $this->pcl_zip(); + } - do_action( 'envato_archive_finished' ); - - } - - /** - * Zip using the native zip command - * - * @access public - * @since 1.4 - * - * @return null - */ - public function zip() { - - $this->archive_method = 'zip'; - - $this->warning( $this->archive_method, shell_exec( 'cd ' . escapeshellarg( $this->root() ) . ' && ' . escapeshellarg( $this->zip_command_path ) . ' -rq ' . escapeshellarg( $this->archive_filepath() ) . ' ./' . ' 2>&1' ) ); - - $this->check_archive(); - - } - - /** - * Fallback for creating zip archives if zip command is unnavailable. - * - * @access public - * @since 1.4 - * - * @param string $path - * @return null - */ - public function zip_archive() { + /** + * The full filepath to the archive file. + * + * @access public + * @since 1.4 + * + * @return string + */ + public function archive_filepath() { + return trailingslashit( $this->path() ) . $this->archive_filename(); + } - $this->errors_to_warnings( $this->archive_method ); - $this->archive_method = 'ziparchive'; + /** + * Helper function to sanitize archive filename. + * + * @access public + * @since 1.4 + * + * @return string + */ + public function archive_filename() { + return strtolower( sanitize_file_name( remove_accents( $this->archive_filename ) ) ); + } - $zip = new ZipArchive(); + /** + * Helper function to sanitize the root directory path. + * + * @access public + * @since 1.4 + * + * @return string + */ + public function root() { + return $this->conform_dir( $this->root ); + } - if ( ! class_exists( 'ZipArchive' ) || ! $zip->open( $this->archive_filepath(), ZIPARCHIVE::CREATE ) ) - return; + /** + * Helper function to sanitize the archive directory path. + * + * @access public + * @since 1.4 + * + * @return string + */ + public function path() { + return $this->conform_dir( $this->path ); + } - $files_added = 0; + /** + * Helper function to return the archive method. + * + * @access public + * @since 1.4 + * + * @return string + */ + public function archive_method() { + return $this->archive_method; + } - foreach ( $this->files() as $file ) { + /** + * Kick off a backup + * + * @access public + * @since 1.4 + * + * @return bool + */ + public function backup() { - if ( is_dir( trailingslashit( $this->root() ) . $file ) ) - $zip->addEmptyDir( trailingslashit( $file ) ); + do_action( 'envato_backup_started', $this ); - elseif ( is_file( trailingslashit( $this->root() ) . $file ) ) - $zip->addFile( trailingslashit( $this->root() ) . $file, $file ); + /* Zip everything up */ + $this->archive(); - if ( ++$files_added % 500 === 0 ) - if ( ! $zip->close() || ! $zip->open( $this->archive_filepath(), ZIPARCHIVE::CREATE ) ) - return; + do_action( 'envato_backup_complete', $this ); } - - if ( $zip->status ) - $this->warning( $this->archive_method, $zip->status ); - - if ( $zip->statusSys ) - $this->warning( $this->archive_method, $zip->statusSys ); - - $zip->close(); - - $this->check_archive(); - - } - - /** - * Fallback for creating zip archives if both zip command - * and ZipArchive are unnavailable. - * - * Uses the PclZip library that ships with WordPress - * - * @access public - * @since 1.4 - * - * @param string $path - * @return null - */ - public function pcl_zip() { - $this->errors_to_warnings( $this->archive_method ); - $this->archive_method = 'pclzip'; - - global $_envato_backup_exclude_string; - - $_envato_backup_exclude_string = $this->exclude_string( 'regex' ); - - $this->load_pclzip(); - - $archive = new PclZip( $this->archive_filepath() ); - - /* Zip up everything */ - if ( ! $archive->add( $this->root(), PCLZIP_OPT_REMOVE_PATH, $this->root(), PCLZIP_CB_PRE_ADD, 'envato_backup_pclzip_callback' ) ) - $this->warning( $this->archive_method, $archive->errorInfo( true ) ); - - unset( $GLOBALS['_envato_backup_exclude_string'] ); + /** + * Zip up all the files. + * + * Attempts to use the shell zip command, if + * thats not available then it fallsback to + * PHP ZipArchive and finally PclZip. + * + * @access public + * @since 1.4 + * + * @return null + */ + public function archive() { + + do_action( 'envato_archive_started' ); + + /* Do we have the path to the zip command */ + if ( $this->zip_command_path ) + $this->zip(); + + /* If not or if the shell zip failed then use ZipArchive */ + if ( empty( $this->archive_verified ) && class_exists( 'ZipArchive' ) && empty( $this->skip_zip_archive ) ) + $this->zip_archive(); + + /* If ZipArchive is unavailable or one of the above failed */ + if ( empty( $this->archive_verified ) ) + $this->pcl_zip(); + + do_action( 'envato_archive_finished' ); - $this->check_archive(); - - } - - /** - * Verify that the archive is valid and contains all the files it should contain. - * - * @access public - * @since 1.4 - * - * @return bool - */ - public function check_archive() { + } - /* If we've already passed then no need to check again */ - if ( ! empty( $this->archive_verified ) ) - return true; - - if ( ! file_exists( $this->archive_filepath() ) ) - $this->error( $this->archive_method(), __( 'The backup file was not created', 'envato-wordpress-toolkit' ) ); + /** + * Zip using the native zip command + * + * @access public + * @since 1.4 + * + * @return null + */ + public function zip() { - /* Verify using the zip command if possible */ - if ( $this->zip_command_path ) { + $this->archive_method = 'zip'; - $verify = shell_exec( escapeshellarg( $this->zip_command_path ) . ' -T ' . escapeshellarg( $this->archive_filepath() ) . ' 2> /dev/null' ); + $this->warning( $this->archive_method, shell_exec( 'cd ' . escapeshellarg( $this->root() ) . ' && ' . escapeshellarg( $this->zip_command_path ) . ' -rq ' . escapeshellarg( $this->archive_filepath() ) . ' ./' . ' 2>&1' ) ); - if ( strpos( $verify, 'OK' ) === false ) - $this->error( $this->archive_method(), $verify ); + $this->check_archive(); } + + /** + * Fallback for creating zip archives if zip command is unnavailable. + * + * @access public + * @since 1.4 + * + * @param string $path + * @return null + */ + public function zip_archive() { + + $this->errors_to_warnings( $this->archive_method ); + $this->archive_method = 'ziparchive'; + + $zip = new ZipArchive(); + + if ( ! class_exists( 'ZipArchive' ) || ! $zip->open( $this->archive_filepath(), ZIPARCHIVE::CREATE ) ) + return; + + $files_added = 0; + + foreach ( $this->files() as $file ) { + + if ( is_dir( trailingslashit( $this->root() ) . $file ) ) + $zip->addEmptyDir( trailingslashit( $file ) ); + + elseif ( is_file( trailingslashit( $this->root() ) . $file ) ) + $zip->addFile( trailingslashit( $this->root() ) . $file, $file ); + + if ( ++$files_added % 500 === 0 ) + if ( ! $zip->close() || ! $zip->open( $this->archive_filepath(), ZIPARCHIVE::CREATE ) ) + return; + + } + + if ( $zip->status ) + $this->warning( $this->archive_method, $zip->status ); + + if ( $zip->statusSys ) + $this->warning( $this->archive_method, $zip->statusSys ); + + $zip->close(); + + $this->check_archive(); - /* If there are errors delete the backup file. */ - if ( $this->errors( $this->archive_method() ) && file_exists( $this->archive_filepath() ) ) - unlink( $this->archive_filepath() ); + } + + /** + * Fallback for creating zip archives if both zip command + * and ZipArchive are unnavailable. + * + * Uses the PclZip library that ships with WordPress + * + * @access public + * @since 1.4 + * + * @param string $path + * @return null + */ + public function pcl_zip() { + + $this->errors_to_warnings( $this->archive_method ); + $this->archive_method = 'pclzip'; + + global $_envato_backup_exclude_string; + + $_envato_backup_exclude_string = $this->exclude_string( 'regex' ); + + $this->load_pclzip(); + + $archive = new PclZip( $this->archive_filepath() ); + + /* Zip up everything */ + if ( ! $archive->add( $this->root(), PCLZIP_OPT_REMOVE_PATH, $this->root(), PCLZIP_CB_PRE_ADD, array( $this, 'pcl_zip_callback' ) ) ) + $this->warning( $this->archive_method, $archive->errorInfo( true ) ); + + unset( $GLOBALS['_envato_backup_exclude_string'] ); + + $this->check_archive(); - if ( $this->errors( $this->archive_method() ) ) + } + + /** + * Add file callback for PclZip, excludes files + * and sets the database dump to be stored in the root + * of the zip + * + * @access private + * @since 1.4 + * @since 1.7.2 (moved into class) + * + * @param string $event + * @param array &$file + * @return bool + */ + function pcl_zip_callback( $event, &$file ) { + + global $_envato_backup_exclude_string; + + /* Don't try to add unreadable files. */ + if ( ! is_readable( $file['filename'] ) || ! file_exists( $file['filename'] ) ) + return false; + + /* Match everything else past the exclude list */ + elseif ( $_envato_backup_exclude_string && preg_match( '(' . $_envato_backup_exclude_string . ')', $file['stored_filename'] ) ) return false; - - return $this->archive_verified = true; - - } - /** - * Generate the array of files to be backed up by looping through - * root, ignored unreadable files and excludes - * - * @access public - * @since 1.4 - * - * @return array - */ - public function files() { + return true; + + } - if ( ! empty( $this->files ) ) - return $this->files; - - $this->files = array(); - - if ( defined( 'RecursiveDirectoryIterator::FOLLOW_SYMLINKS' ) ) { - - $filesystem = new RecursiveIteratorIterator( new RecursiveDirectoryIterator( $this->root(), RecursiveDirectoryIterator::FOLLOW_SYMLINKS ), RecursiveIteratorIterator::SELF_FIRST, RecursiveIteratorIterator::CATCH_GET_CHILD ); - - $excludes = $this->exclude_string( 'regex' ); - - foreach ( $filesystem as $file ) { - - if ( ! $file->isReadable() ) { - $this->unreadable_files[] = $file->getPathName(); - continue; - } - - $pathname = str_ireplace( trailingslashit( $this->root() ), '', $this->conform_dir( $file->getPathname() ) ); - - /* Excludes */ - if ( $excludes && preg_match( '(' . $excludes . ')', $pathname ) ) - continue; - - $this->files[] = $pathname; - + /** + * Verify that the archive is valid and contains all the files it should contain. + * + * @access public + * @since 1.4 + * + * @return bool + */ + public function check_archive() { + + /* If we've already passed then no need to check again */ + if ( ! empty( $this->archive_verified ) ) + return true; + + if ( ! file_exists( $this->archive_filepath() ) ) + $this->error( $this->archive_method(), __( 'The backup file was not created', 'envato-wordpress-toolkit' ) ); + + /* Verify using the zip command if possible */ + if ( $this->zip_command_path ) { + + $verify = shell_exec( escapeshellarg( $this->zip_command_path ) . ' -T ' . escapeshellarg( $this->archive_filepath() ) . ' 2> /dev/null' ); + + if ( strpos( $verify, 'OK' ) === false ) + $this->error( $this->archive_method(), $verify ); + } - - } else { - - $this->files = $this->files_fallback( $this->root() ); + + /* If there are errors delete the backup file. */ + if ( $this->errors( $this->archive_method() ) && file_exists( $this->archive_filepath() ) ) + unlink( $this->archive_filepath() ); + + if ( $this->errors( $this->archive_method() ) ) + return false; + + return $this->archive_verified = true; } - - if ( ! empty( $this->unreadable_files ) ) - $this->warning( $this->archive_method(), __( 'The following files are unreadable and could not be backed up: ', 'envato-wordpress-toolkit' ) . implode( ', ', $this->unreadable_files ) ); - - return $this->files; - } - - /** - * Fallback function for generating a filesystem array - * - * Used if RecursiveDirectoryIterator::FOLLOW_SYMLINKS isn't available - * - * @access private - * @since 1.4 - * - * @param string $dir - * @param array $files. (default: array()) - * @return array - */ - private function files_fallback( $dir, $files = array() ) { - - $handle = opendir( $dir ); - - $excludes = $this->exclude_string( 'regex' ); - - while ( $file = readdir( $handle ) ) : - - /* Ignore current dir and containing dir and any unreadable files or directories */ - if ( $file == '.' || $file == '..' ) - continue; - - $filepath = $this->conform_dir( trailingslashit( $dir ) . $file ); - $file = str_ireplace( trailingslashit( $this->root() ), '', $filepath ); - - if ( ! is_readable( $filepath ) ) { - $this->unreadable_files[] = $filepath; - continue; + /** + * Generate the array of files to be backed up by looping through + * root, ignored unreadable files and excludes + * + * @access public + * @since 1.4 + * + * @return array + */ + public function files() { + + if ( ! empty( $this->files ) ) + return $this->files; + + $this->files = array(); + + if ( defined( 'RecursiveDirectoryIterator::FOLLOW_SYMLINKS' ) ) { + + $filesystem = new RecursiveIteratorIterator( new RecursiveDirectoryIterator( $this->root(), RecursiveDirectoryIterator::FOLLOW_SYMLINKS ), RecursiveIteratorIterator::SELF_FIRST, RecursiveIteratorIterator::CATCH_GET_CHILD ); + + $excludes = $this->exclude_string( 'regex' ); + + foreach ( $filesystem as $file ) { + + if ( ! $file->isReadable() ) { + $this->unreadable_files[] = $file->getPathName(); + continue; + } + + $pathname = str_ireplace( trailingslashit( $this->root() ), '', $this->conform_dir( $file->getPathname() ) ); + + /* Excludes */ + if ( $excludes && preg_match( '(' . $excludes . ')', $pathname ) ) + continue; + + $this->files[] = $pathname; + + } + + } else { + + $this->files = $this->files_fallback( $this->root() ); + } + + if ( ! empty( $this->unreadable_files ) ) + $this->warning( $this->archive_method(), __( 'The following files are unreadable and could not be backed up: ', 'envato-wordpress-toolkit' ) . implode( ', ', $this->unreadable_files ) ); + + return $this->files; - /* Skip the backups dir and any excluded paths */ - if ( ( $excludes && preg_match( '(' . $excludes . ')', $file ) ) ) - continue; - - $files[] = $file; - - if ( is_dir( $filepath ) ) - $files = $this->files_fallback( $filepath, $files ); - - endwhile; - - return $files; - - } - - /** - * Helper function to load the PclZip library. - * - * @access private - * @since 1.4 - * - * @return null - */ - private function load_pclzip() { - - /* Load PclZip */ - if ( ! defined( 'PCLZIP_TEMPORARY_DIR' ) ) - define( 'PCLZIP_TEMPORARY_DIR', trailingslashit( $this->path() ) ); - - require_once( ABSPATH . 'wp-admin/includes/class-pclzip.php' ); - - } - - /** - * Attempt to work out the path to the zip command - * - * @access public - * @since 1.4 - * - * @return string - */ - public function guess_zip_command_path() { + } - /* Check shell_exec is available and hasn't been explicitly bypassed */ - if ( ! $this->shell_exec_available() ) - return ''; - - /* List of possible zip locations */ - $zip_locations = array( - '/usr/bin/zip' - ); + /** + * Fallback function for generating a filesystem array + * + * Used if RecursiveDirectoryIterator::FOLLOW_SYMLINKS isn't available + * + * @access private + * @since 1.4 + * + * @param string $dir + * @param array $files. (default: array()) + * @return array + */ + private function files_fallback( $dir, $files = array() ) { + + $handle = opendir( $dir ); + + $excludes = $this->exclude_string( 'regex' ); + + while ( $file = readdir( $handle ) ) : + + /* Ignore current dir and containing dir and any unreadable files or directories */ + if ( $file == '.' || $file == '..' ) + continue; + + $filepath = $this->conform_dir( trailingslashit( $dir ) . $file ); + $file = str_ireplace( trailingslashit( $this->root() ), '', $filepath ); + + if ( ! is_readable( $filepath ) ) { + $this->unreadable_files[] = $filepath; + continue; + } + + /* Skip the backups dir and any excluded paths */ + if ( ( $excludes && preg_match( '(' . $excludes . ')', $file ) ) ) + continue; + + $files[] = $file; + + if ( is_dir( $filepath ) ) + $files = $this->files_fallback( $filepath, $files ); + + endwhile; + + return $files; - if ( is_null( shell_exec( 'hash zip 2>&1' ) ) ) - return 'zip'; + } - /* Find the one which works */ - foreach ( $zip_locations as $location ) - if ( @file_exists( $this->conform_dir( $location ) ) ) - return $location; + /** + * Helper function to load the PclZip library. + * + * @access private + * @since 1.4 + * + * @return null + */ + private function load_pclzip() { + + /* Load PclZip */ + if ( ! defined( 'PCLZIP_TEMPORARY_DIR' ) ) + define( 'PCLZIP_TEMPORARY_DIR', trailingslashit( $this->path() ) ); + + require_once( ABSPATH . 'wp-admin/includes/class-pclzip.php' ); - return ''; - - } - - /** - * Generate the exclude param string for the zip backup - * - * Takes the exclude rules and formats them for use with either - * the shell zip command or pclzip - * - * @access public - * @since 1.4 - * - * @param string $context. (default: 'zip') - * @return string - */ - public function exclude_string( $context = 'zip' ) { + } - /* Return a comma separated list by default */ - $separator = ', '; - $wildcard = ''; - - /* The zip command */ - if ( $context == 'zip' ) { + /** + * Attempt to work out the path to the zip command + * + * @access public + * @since 1.4 + * + * @return string + */ + public function guess_zip_command_path() { + + /* Check shell_exec is available and hasn't been explicitly bypassed */ + if ( ! $this->shell_exec_available() ) + return ''; - $wildcard = '*'; - $separator = ' -x '; - - /* The PclZip fallback library */ - } else if ( $context == 'regex' ) { + /* List of possible zip locations */ + $zip_locations = array( + '/usr/bin/zip' + ); + + if ( is_null( shell_exec( 'hash zip 2>&1' ) ) ) + return 'zip'; - $wildcard = '([\s\S]*?)'; - $separator = '|'; + /* Find the one which works */ + foreach ( $zip_locations as $location ) + if ( @file_exists( $this->conform_dir( $location ) ) ) + return $location; + + return ''; } - - /* Sanitize the excludes */ - $excludes = array_filter( array_unique( array_map( 'trim', (array) $this->excludes ) ) ); - - /* If path() is inside root(), exclude it */ - if ( strpos( $this->path(), $this->root() ) !== false ) - $excludes[] = trailingslashit( $this->path() ); - - foreach( $excludes as $key => &$rule ) { - - $file = $absolute = $fragment = false; - - /* Files don't end with / */ - if ( ! in_array( substr( $rule, -1 ), array( '\\', '/' ) ) ) { - $file = true; + + /** + * Generate the exclude param string for the zip backup + * + * Takes the exclude rules and formats them for use with either + * the shell zip command or pclzip + * + * @access public + * @since 1.4 + * + * @param string $context. (default: 'zip') + * @return string + */ + public function exclude_string( $context = 'zip' ) { + + /* Return a comma separated list by default */ + $separator = ', '; + $wildcard = ''; - /* If rule starts with a / then treat as absolute path */ - } else if ( in_array( substr( $rule, 0, 1 ), array( '\\', '/' ) ) ) { - $absolute = true; + /* The zip command */ + if ( $context == 'zip' ) { + + $wildcard = '*'; + $separator = ' -x '; - /* Otherwise treat as dir fragment */ - } else { - $fragment = true; + /* The PclZip fallback library */ + } else if ( $context == 'regex' ) { - } + $wildcard = '([\s\S]*?)'; + $separator = '|'; - /* Strip $this->root and conform */ - $rule = str_ireplace( $this->root(), '', untrailingslashit( $this->conform_dir( $rule ) ) ); + } - /* Strip the preceeding slash */ - if ( in_array( substr( $rule, 0, 1 ), array( '\\', '/' ) ) ) - $rule = substr( $rule, 1 ); + /* Sanitize the excludes */ + $excludes = array_filter( array_unique( array_map( 'trim', (array) $this->excludes ) ) ); - /* Escape string for regex */ - if ( $context == 'regex' ) - $rule = str_replace( '.', '\.', $rule ); + /* If path() is inside root(), exclude it */ + if ( strpos( $this->path(), $this->root() ) !== false ) + $excludes[] = trailingslashit( $this->path() ); - /* Convert any existing wildcards */ - if ( $wildcard != '*' && strpos( $rule, '*' ) !== false ) - $rule = str_replace( '*', $wildcard, $rule ); + foreach( $excludes as $key => &$rule ) { - /* Wrap directory fragments and files in wildcards for zip */ - if ( $context == 'zip' && ( $fragment || $file ) ) - $rule = $wildcard . $rule . $wildcard; + $file = $absolute = $fragment = false; + + /* Files don't end with / */ + if ( ! in_array( substr( $rule, -1 ), array( '\\', '/' ) ) ) { + $file = true; + + /* If rule starts with a / then treat as absolute path */ + } else if ( in_array( substr( $rule, 0, 1 ), array( '\\', '/' ) ) ) { + $absolute = true; + + /* Otherwise treat as dir fragment */ + } else { + $fragment = true; + + } + + /* Strip $this->root and conform */ + $rule = str_ireplace( $this->root(), '', untrailingslashit( $this->conform_dir( $rule ) ) ); + + /* Strip the preceeding slash */ + if ( in_array( substr( $rule, 0, 1 ), array( '\\', '/' ) ) ) + $rule = substr( $rule, 1 ); + + /* Escape string for regex */ + if ( $context == 'regex' ) + $rule = str_replace( '.', '\.', $rule ); + + /* Convert any existing wildcards */ + if ( $wildcard != '*' && strpos( $rule, '*' ) !== false ) + $rule = str_replace( '*', $wildcard, $rule ); + + /* Wrap directory fragments and files in wildcards for zip */ + if ( $context == 'zip' && ( $fragment || $file ) ) + $rule = $wildcard . $rule . $wildcard; + + /* Add a wildcard to the end of absolute url for zips */ + if ( $context == 'zip' && $absolute ) + $rule .= $wildcard; + + /* Add and end carrot to files for pclzip but only if it doesn't end in a wildcard */ + if ( $file && $context == 'regex' ) + $rule .= '$'; + + /* Add a start carrot to absolute urls for pclzip */ + if ( $absolute && $context == 'regex' ) + $rule = '^' . $rule; - /* Add a wildcard to the end of absolute url for zips */ - if ( $context == 'zip' && $absolute ) - $rule .= $wildcard; + } - /* Add and end carrot to files for pclzip but only if it doesn't end in a wildcard */ - if ( $file && $context == 'regex' ) - $rule .= '$'; + /* Escape shell args for zip command */ + if ( $context == 'zip' ) + $excludes = array_map( 'escapeshellarg', array_unique( $excludes ) ); - /* Add a start carrot to absolute urls for pclzip */ - if ( $absolute && $context == 'regex' ) - $rule = '^' . $rule; + return implode( $separator, $excludes ); } + + /** + * Check whether safe mode is active or not + * + * @access public + * @since 1.4 + * + * @return bool + */ + public function is_safe_mode_active() { + + if ( $safe_mode = ini_get( 'safe_mode' ) && strtolower( $safe_mode ) != 'off' ) + return true; + + return false; - /* Escape shell args for zip command */ - if ( $context == 'zip' ) - $excludes = array_map( 'escapeshellarg', array_unique( $excludes ) ); - - return implode( $separator, $excludes ); + } - } - - /** - * Check whether safe mode is active or not - * - * @access public - * @since 1.4 - * - * @return bool - */ - public function is_safe_mode_active() { - - if ( $safe_mode = ini_get( 'safe_mode' ) && strtolower( $safe_mode ) != 'off' ) + /** + * Check whether shell_exec has been disabled. + * + * @access private + * @since 1.4 + * + * @return bool + */ + private function shell_exec_available() { + + /* Are we in Safe Mode */ + if ( $this->is_safe_mode_active() ) + return false; + + /* Is shell_exec disabled? */ + if ( in_array( 'shell_exec', array_map( 'trim', explode( ',', ini_get( 'disable_functions' ) ) ) ) ) + return false; + + /* Can we issue a simple echo command? */ + if ( ! @shell_exec( 'echo envatobackup' ) ) + return false; + return true; - return false; - - } - - /** - * Check whether shell_exec has been disabled. - * - * @access private - * @since 1.4 - * - * @return bool - */ - private function shell_exec_available() { + } - /* Are we in Safe Mode */ - if ( $this->is_safe_mode_active() ) - return false; - - /* Is shell_exec disabled? */ - if ( in_array( 'shell_exec', array_map( 'trim', explode( ',', ini_get( 'disable_functions' ) ) ) ) ) - return false; - - /* Can we issue a simple echo command? */ - if ( ! @shell_exec( 'echo envatobackup' ) ) - return false; + /** + * Sanitize a directory path + * + * @access public + * @since 1.4 + * + * @param string $dir + * @param bool $recursive. (default: false) + * @return string $dir + */ + public function conform_dir( $dir, $recursive = false ) { + + /* Assume empty dir is root */ + if ( ! $dir ) + $dir = '/'; + + /* Replace single forward slash (looks like double slash because we have to escape it) */ + $dir = str_replace( '\\', '/', $dir ); + $dir = str_replace( '//', '/', $dir ); + + /* Remove the trailing slash */ + if ( $dir !== '/' ) + $dir = untrailingslashit( $dir ); + + /* Carry on until completely normalized */ + if ( ! $recursive && $this->conform_dir( $dir, true ) != $dir ) + return $this->conform_dir( $dir ); + + return (string) $dir; - return true; - - } - - /** - * Sanitize a directory path - * - * @access public - * @since 1.4 - * - * @param string $dir - * @param bool $recursive. (default: false) - * @return string $dir - */ - public function conform_dir( $dir, $recursive = false ) { + } - /* Assume empty dir is root */ - if ( ! $dir ) - $dir = '/'; + /** + * Get the errors + * + * @access public + * @since 1.4 + * + * @param string $context + * @return mixed + */ + public function errors( $context = null ) { + + if ( ! empty( $context ) ) + return isset( $this->errors[$context] ) ? $this->errors[$context] : array(); + + return $this->errors; - /* Replace single forward slash (looks like double slash because we have to escape it) */ - $dir = str_replace( '\\', '/', $dir ); - $dir = str_replace( '//', '/', $dir ); + } + + /** + * Add an error to the errors stack + * + * @access private + * @since 1.4 + * + * @param string $context + * @param mixed $error + * @return null + */ + private function error( $context, $error ) { - /* Remove the trailing slash */ - if ( $dir !== '/' ) - $dir = untrailingslashit( $dir ); + if ( empty( $context ) || empty( $error ) ) + return; - /* Carry on until completely normalized */ - if ( ! $recursive && $this->conform_dir( $dir, true ) != $dir ) - return $this->conform_dir( $dir ); + $this->errors[$context][$_key = md5( implode( ':' , (array) $error ) )] = $error; - return (string) $dir; - - } - - /** - * Get the errors - * - * @access public - * @since 1.4 - * - * @param string $context - * @return mixed - */ - public function errors( $context = null ) { + } - if ( ! empty( $context ) ) - return isset( $this->errors[$context] ) ? $this->errors[$context] : array(); + /** + * Migrate errors to warnings + * + * @access private + * @since 1.4 + * + * @param string $context. (default: null) + * @return null + */ + private function errors_to_warnings( $context = null ) { + + $errors = empty( $context ) ? $this->errors() : array( $context => $this->errors( $context ) ); + + if ( empty( $errors ) ) + return; + + foreach ( $errors as $error_context => $errors ) + foreach( $errors as $error ) + $this->warning( $error_context, $error ); + + if ( $context ) + unset( $this->errors[$context] ); + + else + $this->errors = array(); - return $this->errors; - - } - - /** - * Add an error to the errors stack - * - * @access private - * @since 1.4 - * - * @param string $context - * @param mixed $error - * @return null - */ - private function error( $context, $error ) { - - if ( empty( $context ) || empty( $error ) ) - return; - - $this->errors[$context][$_key = md5( implode( ':' , (array) $error ) )] = $error; - - } - - /** - * Migrate errors to warnings - * - * @access private - * @since 1.4 - * - * @param string $context. (default: null) - * @return null - */ - private function errors_to_warnings( $context = null ) { + } - $errors = empty( $context ) ? $this->errors() : array( $context => $this->errors( $context ) ); + /** + * Get the warnings + * + * @access public + * @since 1.4 + * + * @return null + */ + public function warnings( $context = null ) { - if ( empty( $errors ) ) - return; + if ( ! empty( $context ) ) + return isset( $this->warnings[$context] ) ? $this->warnings[$context] : array(); - foreach ( $errors as $error_context => $errors ) - foreach( $errors as $error ) - $this->warning( $error_context, $error ); + return $this->warnings; - if ( $context ) - unset( $this->errors[$context] ); - - else - $this->errors = array(); - - } - - /** - * Get the warnings - * - * @access public - * @since 1.4 - * - * @return null - */ - public function warnings( $context = null ) { - - if ( ! empty( $context ) ) - return isset( $this->warnings[$context] ) ? $this->warnings[$context] : array(); - - return $this->warnings; - - } - - /** - * Add an warning to the warnings stack - * - * @access private - * @since 1.4 - * - * @param string $context - * @param mixed $warning - * @return null - */ - private function warning( $context, $warning ) { - - if ( empty( $context ) || empty( $warning ) ) - return; - - $this->warnings[$context][$_key = md5( implode( ':' , (array) $warning ) )] = $warning; - - } - - /** - * Custom error handler for catching errors - * - * @access private - * @since 1.4 - * - * @param string $type - * @param string $message - * @param string $file - * @param string $line - * @return null - */ - public function error_handler( $type ) { + } - if ( ( defined( 'E_DEPRECATED' ) && $type == E_DEPRECATED ) || ( defined( 'E_STRICT' ) && $type == E_STRICT ) || error_reporting() === 0 ) - return false; + /** + * Add an warning to the warnings stack + * + * @access private + * @since 1.4 + * + * @param string $context + * @param mixed $warning + * @return null + */ + private function warning( $context, $warning ) { - $args = func_get_args(); + if ( empty( $context ) || empty( $warning ) ) + return; - $this->warning( 'php', array_splice( $args, 0, 4 ) ); + $this->warnings[$context][$_key = md5( implode( ':' , (array) $warning ) )] = $warning; - return false; - - } - -} - -/** - * Add file callback for PclZip, excludes files - * and sets the database dump to be stored in the root - * of the zip - * - * @access private - * @since 1.4 - * - * @param string $event - * @param array &$file - * @return bool - */ -function envato_backup_pclzip_callback( $event, &$file ) { - - global $_envato_backup_exclude_string; - - /* Don't try to add unreadable files. */ - if ( ! is_readable( $file['filename'] ) || ! file_exists( $file['filename'] ) ) - return false; + } - /* Match everything else past the exclude list */ - elseif ( $_envato_backup_exclude_string && preg_match( '(' . $_envato_backup_exclude_string . ')', $file['stored_filename'] ) ) - return false; + /** + * Custom error handler for catching errors + * + * @access private + * @since 1.4 + * + * @param string $type + * @param string $message + * @param string $file + * @param string $line + * @return null + */ + public function error_handler( $type ) { + + if ( ( defined( 'E_DEPRECATED' ) && $type == E_DEPRECATED ) || ( defined( 'E_STRICT' ) && $type == E_STRICT ) || error_reporting() === 0 ) + return false; + + $args = func_get_args(); + + $this->warning( 'php', array_splice( $args, 0, 4 ) ); + + return false; + + } - return true; + } } diff --git a/index.php b/index.php index d006e4b..2a544bd 100644 --- a/index.php +++ b/index.php @@ -7,1194 +7,1202 @@ * Author: Envato * Author URI: http://envato.com */ -class Envato_WP_Toolkit { - - /** - * The Envato Protected API object - * - * @access private - * @since 1.1 - * - * @var object - */ - protected $protected_api; - - /** - * Nonce for AJAX notifications - * - * @access private - * @since 1.7.0 - * - * @var string - */ - protected $ajax_notification_nonce; - - /** - * PHP5 constructor method. - * - * This method adds other methods to specific hooks within WordPress. - * - * @uses add_action() - * - * @access public - * @since 1.0 - * - * @return void - */ - public function __construct() { - $this->_constants(); - $this->_includes(); - $this->_hooks(); - } - - /** - * Defines the constants for use within the plugin. - * - * @access private - * @since 1.0 - * @updated 1.6 - * - * @return void - */ - protected function _constants() { - /** - * Plugin Version - */ - define( 'EWPT_PLUGIN_VER', '1.7.2' ); - - /** - * Plugin Name - */ - define( 'EWPT_PLUGIN_NAME', __( 'Envato WordPress Toolkit', 'envato-wordpress-toolkit' ) ); +if ( ! class_exists( 'Envato_WP_Toolkit' ) ) { + + class Envato_WP_Toolkit { /** - * Plugin Slug + * The Envato Protected API object + * + * @access private + * @since 1.1 + * + * @var object */ - define( 'EWPT_PLUGIN_SLUG', 'envato-wordpress-toolkit' ); + protected $protected_api; /** - * Maximum request time + * Nonce for AJAX notifications + * + * @access private + * @since 1.7.0 + * + * @var string */ - define( 'EWPT_PLUGIN_MAX_EXECUTION_TIME' , 60 * 5 ); + protected $ajax_notification_nonce; /** - * Plugin Directory Path + * PHP5 constructor method. + * + * This method adds other methods to specific hooks within WordPress. + * + * @uses add_action() + * + * @access public + * @since 1.0 + * + * @return void */ - define( 'EWPT_PLUGIN_DIR', plugin_dir_path( __FILE__ ) ); + public function __construct() { + $this->_constants(); + $this->_includes(); + $this->_hooks(); + } /** - * Plugin Directory URL + * Defines the constants for use within the plugin. + * + * @access private + * @since 1.0 + * @updated 1.6 + * + * @return void */ - define( 'EWPT_PLUGIN_URL', plugin_dir_url( __FILE__ ) ); + protected function _constants() { + /** + * Plugin Version + */ + define( 'EWPT_PLUGIN_VER', '1.7.2' ); + + /** + * Plugin Name + */ + define( 'EWPT_PLUGIN_NAME', __( 'Envato WordPress Toolkit', 'envato-wordpress-toolkit' ) ); + + /** + * Plugin Slug + */ + define( 'EWPT_PLUGIN_SLUG', 'envato-wordpress-toolkit' ); + + /** + * Maximum request time + */ + define( 'EWPT_PLUGIN_MAX_EXECUTION_TIME' , 60 * 5 ); + + /** + * Plugin Directory Path + */ + define( 'EWPT_PLUGIN_DIR', plugin_dir_path( __FILE__ ) ); + + /** + * Plugin Directory URL + */ + define( 'EWPT_PLUGIN_URL', plugin_dir_url( __FILE__ ) ); + + /** + * Theme Backup Directory Path + */ + define( 'EWPT_BACKUP_DIR', WP_CONTENT_DIR . '/envato-backups/' ); + + /** + * Theme Backup Directory URL + */ + define( 'EWPT_BACKUP_URL', WP_CONTENT_URL . '/envato-backups/' ); + + /** + * Create a key for the .htaccess secure download link. + * + * @uses NONCE_KEY Defined in the WP root config.php + */ + define( 'EWPT_SECURE_KEY', md5( NONCE_KEY ) ); + + } /** - * Theme Backup Directory Path - */ - define( 'EWPT_BACKUP_DIR', WP_CONTENT_DIR . '/envato-backups/' ); - - /** - * Theme Backup Directory URL + * Include required files + * + * @since 1.0 + * @access private + * + * @return void */ - define( 'EWPT_BACKUP_URL', WP_CONTENT_URL . '/envato-backups/' ); + protected function _includes() { + /* load required files */ + if ( ! class_exists( 'Envato_Theme_Upgrader' ) ) { + require_once( EWPT_PLUGIN_DIR . 'includes/class-wp-upgrader.php' ); + } + if ( ! class_exists( 'Envato_Backup' ) ) { + require_once( EWPT_PLUGIN_DIR . 'includes/class-envato-backup.php' ); + } + if ( ! class_exists( 'Envato_Protected_API' ) ) { + require_once( EWPT_PLUGIN_DIR . 'includes/class-envato-api.php' ); + } + $options = get_option( EWPT_PLUGIN_SLUG ); + if ( ! class_exists( 'WP_GitHub_Updater' ) && ! isset( $options['deactivate_github_updater'] ) ) { + require_once( EWPT_PLUGIN_DIR . 'includes/class-github-updater.php' ); + } + } /** - * Create a key for the .htaccess secure download link. + * Setup the default filters and actions + * + * @uses add_action() To add various actions + * + * @access private + * @since 1.0 * - * @uses NONCE_KEY Defined in the WP root config.php + * @return void */ - define( 'EWPT_SECURE_KEY', md5( NONCE_KEY ) ); - - } + protected function _hooks() { + /** + * add envato menu item, change menu filter for multisite + */ + if ( is_multisite() ) { + add_action( 'network_admin_menu', array( $this, '_envato_menu' ), 101 ); + } else { + add_action( 'admin_menu', array( $this, '_envato_menu' ), 101 ); + } + + /** + * Menu Icon CSS + */ + add_action( 'admin_head', array( $this, '_menu_icon' ) ); + + /** + * Load text domain + */ + add_action( 'plugins_loaded', array( $this, '_load_textdomain' ) ); + + /** + * Create AJAX nonce + */ + add_action( 'init', array( $this, '_ajax_notification_nonce' ) ); + + /** + * loaded during admin init + */ + add_action( 'admin_init', array( $this, '_admin_init' ) ); - /** - * Include required files - * - * @since 1.0 - * @access private - * - * @return void - */ - protected function _includes() { - /* load required files */ - foreach ( array( 'class-wp-upgrader', 'class-envato-backup' ) as $file ) - require_once( EWPT_PLUGIN_DIR . 'includes/' . $file . '.php' ); - if ( ! class_exists( 'Envato_Protected_API' ) ) { - require_once( EWPT_PLUGIN_DIR . 'includes/class-envato-api.php' ); - } - $options = get_option( EWPT_PLUGIN_SLUG ); - if ( ! class_exists( 'WP_GitHub_Updater' ) && ! isset( $options['deactivate_github_updater'] ) ) { - require_once( EWPT_PLUGIN_DIR . 'includes/class-github-updater.php' ); - } - } + /** + * change link URL & text after install & upgrade + */ + add_filter( 'install_theme_complete_actions', array( $this, '_complete_actions' ), 10, 1 ); + add_filter( 'update_theme_complete_actions', array( $this, '_complete_actions' ), 10, 1 ); + add_filter( 'http_request_args', array( $this , '_http_request_args' ), 10, 1 ); + + add_action( 'wp_ajax_hide_admin_notification', array( $this, '_hide_admin_notification' ) ); - /** - * Setup the default filters and actions - * - * @uses add_action() To add various actions - * - * @access private - * @since 1.0 - * - * @return void - */ - protected function _hooks() { - /** - * add envato menu item, change menu filter for multisite - */ - if ( is_multisite() ) { - add_action( 'network_admin_menu', array( $this, '_envato_menu' ), 101 ); - } else { - add_action( 'admin_menu', array( $this, '_envato_menu' ), 101 ); } /** - * Menu Icon CSS - */ - add_action( 'admin_head', array( $this, '_menu_icon' ) ); - + * Loads the text domain. + * + * @return void + * + * @access private + * @since 1.7.1 + */ + public function _load_textdomain() { + + load_plugin_textdomain( 'envato-wordpress-toolkit', false, dirname( plugin_basename( __FILE__ ) ) . '/languages' ); + + } + /** - * Load text domain + * Create a nonce for AJAX notifications + * + * @uses wp_create_nonce() Generates and returns a nonce. + * + * @access private + * @since 1.7.0 + * + * @return void */ - add_action( 'plugins_loaded', array( $this, '_load_textdomain' ) ); + public function _ajax_notification_nonce() { + + /* only if in the admin area */ + if ( is_admin() ) + $this->ajax_notification_nonce = wp_create_nonce( 'ajax-notification-nonce' ); + + } /** - * Create AJAX nonce + * Adds the Envato menu item + * + * @access private + * @since 1.0 + * + * @return void */ - add_action( 'init', array( $this, '_ajax_notification_nonce' ) ); + public function _envato_menu() { + + /** + * Stop Mojo Marketplace from tracking your movements! + */ + remove_action( 'admin_footer', 'mm_ux_log', 9 ); + + $menu_page = add_menu_page( EWPT_PLUGIN_NAME, __( 'Envato Toolkit', 'envato-wordpress-toolkit' ), 'manage_options', EWPT_PLUGIN_SLUG, array( $this, '_envato_menu_page' ), null, 58 ); + + add_action('admin_print_scripts-' . $menu_page, array( $this, '_envato_load_scripts' ) ); + add_action('admin_print_styles-' . $menu_page, array( $this, '_envato_load_styles' ) ); + } /** - * loaded during admin init - */ - add_action( 'admin_init', array( $this, '_admin_init' ) ); - - /** - * change link URL & text after install & upgrade - */ - add_filter( 'install_theme_complete_actions', array( $this, '_complete_actions' ), 10, 1 ); - add_filter( 'update_theme_complete_actions', array( $this, '_complete_actions' ), 10, 1 ); - add_filter( 'http_request_args', array( $this , '_http_request_args' ), 10, 1 ); - - add_action( 'wp_ajax_hide_admin_notification', array( $this, '_hide_admin_notification' ) ); - - } - - /** - * Loads the text domain. + * Menu Font Icon CSS * - * @return void + * Changes the menu image icon to a font based version. * * @access private * @since 1.7.1 + * + * @return string Return icon CSS. */ - public function _load_textdomain() { - - load_plugin_textdomain( 'envato-wordpress-toolkit', false, dirname( plugin_basename( __FILE__ ) ) . '/languages' ); + public function _menu_icon() { + global $wp_version; - } - - /** - * Create a nonce for AJAX notifications - * - * @uses wp_create_nonce() Generates and returns a nonce. - * - * @access private - * @since 1.7.0 - * - * @return void - */ - public function _ajax_notification_nonce() { - - /* only if in the admin area */ - if ( is_admin() ) - $this->ajax_notification_nonce = wp_create_nonce( 'ajax-notification-nonce' ); + $wp_38plus = version_compare( $wp_version, '3.8', '>=' ) ? true : false; + $fontsize = $wp_38plus ? '20px' : '16px'; + $wp_38minus = ''; - } - - /** - * Adds the Envato menu item - * - * @access private - * @since 1.0 - * - * @return void - */ - public function _envato_menu() { + if ( ! $wp_38plus ) { + $wp_38minus = ' + #adminmenu .toplevel_page_envato-wordpress-toolkit .menu-icon-generic div.wp-menu-image { + background: none; + } + #adminmenu .toplevel_page_envato-wordpress-toolkit .menu-icon-generic div.wp-menu-image:before { + padding-left: 6px; + }'; + } + + echo ' + + '; + } /** - * Stop Mojo Marketplace from tracking your movements! + * Loads the scripts for the plugin + * + * @access private + * @since 1.0 + * + * @return void */ - remove_action( 'admin_footer', 'mm_ux_log', 9 ); + public function _envato_load_scripts() { + wp_enqueue_script( 'theme-preview' ); + wp_enqueue_script( 'ajax-notification', EWPT_PLUGIN_URL . 'assets/js/ajax-notification.js', false, EWPT_PLUGIN_VER ); + } - $menu_page = add_menu_page( EWPT_PLUGIN_NAME, __( 'Envato Toolkit', 'envato-wordpress-toolkit' ), 'manage_options', EWPT_PLUGIN_SLUG, array( $this, '_envato_menu_page' ), null, 58 ); + /** + * Loads the styles for the plugin + * + * @access private + * @since 1.0 + * + * @return void + */ + public function _envato_load_styles() { + wp_enqueue_style( 'envato-wp-updater', EWPT_PLUGIN_URL . 'assets/css/style.css', false, EWPT_PLUGIN_VER, 'all' ); + } - add_action('admin_print_scripts-' . $menu_page, array( $this, '_envato_load_scripts' ) ); - add_action('admin_print_styles-' . $menu_page, array( $this, '_envato_load_styles' ) ); - } + /** + * Envato Updater HTML + * + * Creates the page used to verify themes for auto install/update + * + * @access private + * @since 1.0 + * @updated 1.4 + * + * @return string Returns the verification form & themes list + */ + public function _envato_menu_page() { + if ( ! current_user_can( 'manage_options' ) ) + wp_die( __( 'You do not have sufficient permissions to access this page.', 'envato-wordpress-toolkit' ) ); + + /* read in existing API value from database */ + $options = get_option( EWPT_PLUGIN_SLUG ); - /** - * Menu Font Icon CSS - * - * Changes the menu image icon to a font based version. - * - * @access private - * @since 1.7.1 - * - * @return string Return icon CSS. - */ - public function _menu_icon() { - global $wp_version; - - $wp_38plus = version_compare( $wp_version, '3.8', '>=' ) ? true : false; - $fontsize = $wp_38plus ? '20px' : '16px'; - $wp_38minus = ''; - - if ( ! $wp_38plus ) { - $wp_38minus = ' - #adminmenu .toplevel_page_envato-wordpress-toolkit .menu-icon-generic div.wp-menu-image { - background: none; + /* display environment errors */ + if ( ! empty( $options['env_errors'] ) ) { + foreach ( $options['env_errors'] as $k => $v ) { + if ( empty( $options['dismissed_errors'][$k] ) ) { + echo '
' . $v . '
'; + } + } } - #adminmenu .toplevel_page_envato-wordpress-toolkit .menu-icon-generic div.wp-menu-image:before { - padding-left: 6px; - }'; - } - echo ' - - '; - } - - /** - * Loads the scripts for the plugin - * - * @access private - * @since 1.0 - * - * @return void - */ - public function _envato_load_scripts() { - wp_enqueue_script( 'theme-preview' ); - wp_enqueue_script( 'ajax-notification', EWPT_PLUGIN_URL . 'assets/js/ajax-notification.js', false, EWPT_PLUGIN_VER ); - } - - /** - * Loads the styles for the plugin - * - * @access private - * @since 1.0 - * - * @return void - */ - public function _envato_load_styles() { - wp_enqueue_style( 'envato-wp-updater', EWPT_PLUGIN_URL . 'assets/css/style.css', false, EWPT_PLUGIN_VER, 'all' ); - } - /** - * Envato Updater HTML - * - * Creates the page used to verify themes for auto install/update - * - * @access private - * @since 1.0 - * @updated 1.4 - * - * @return string Returns the verification form & themes list - */ - public function _envato_menu_page() { - if ( ! current_user_can( 'manage_options' ) ) - wp_die( __( 'You do not have sufficient permissions to access this page.', 'envato-wordpress-toolkit' ) ); - - /* read in existing API value from database */ - $options = get_option( EWPT_PLUGIN_SLUG ); - - /* display environment errors */ - if ( ! empty( $options['env_errors'] ) ) { - foreach ( $options['env_errors'] as $k => $v ) { - if ( empty( $options['dismissed_errors'][$k] ) ) { - echo '
' . $v . '
'; + /* execute theme actions */ + if ( isset( $_GET['action'] ) && isset( $_GET['theme'] ) ) { + if ( 'install-theme' == $_GET['action'] && is_array( $themes ) ) { + $this->_install_theme( $_GET['theme'], $themes ); + } else if ( 'upgrade-theme' == $_GET['action'] && isset( $_GET['item_id'] ) ) { + $this->_upgrade_theme( $_GET['theme'], $_GET['item_id'] ); } - } - } - - $user_name = ( isset( $options['user_name'] ) ) ? $options['user_name'] : ''; - $api_key = ( isset( $options['api_key'] ) ) ? $options['api_key'] : ''; - - $this->protected_api = new Envato_Protected_API( $user_name, $api_key ); - - /* get purchased marketplace themes */ - $themes = $this->protected_api->wp_list_themes(); - - /* display API errors */ - if ( $errors = $this->protected_api->api_errors() ) { - foreach( $errors as $k => $v ) { - if ( $k !== 'http_code' && ( $user_name || $api_key ) ) - echo '

' . $v . '

'; - } - } - - /* display update messages */ - if ( empty( $errors ) ) { - echo ( isset( $_GET[ 'settings-updated' ] ) ) ? '

' . __( 'User Settings Updated.', 'envato-wordpress-toolkit' ) . '

' : ''; - echo ( isset( $_GET[ 'activated' ] ) ) ? '

' . __( 'Theme Activated.', 'envato-wordpress-toolkit' ) . '

' : ''; - echo ( isset( $_GET[ 'deleted' ] ) ) ? '

' . __( 'Theme Deleted.', 'envato-wordpress-toolkit' ) . '

' : ''; - } - - /* execute theme actions */ - if ( isset( $_GET['action'] ) && isset( $_GET['theme'] ) ) { - if ( 'install-theme' == $_GET['action'] && is_array( $themes ) ) { - $this->_install_theme( $_GET['theme'], $themes ); - } else if ( 'upgrade-theme' == $_GET['action'] && isset( $_GET['item_id'] ) ) { - $this->_upgrade_theme( $_GET['theme'], $_GET['item_id'] ); - } - /* display normal views */ - } else { - - /* no errors & themes are available */ - if ( empty( $errors ) && count( $themes ) > 0 ) { - - /* get WP installed themes */ - if ( function_exists( 'wp_get_themes' ) ) - $get_themes = wp_get_themes(); - else - $get_themes = get_themes(); - - /* empty premium themes array */ - $premium_themes = array(); + /* display normal views */ + } else { + + /* no errors & themes are available */ + if ( empty( $errors ) && count( $themes ) > 0 ) { - /* loop through the marketplace themes */ - if ( ! empty( $themes ) && is_array( $themes ) ) { - foreach( $themes as $theme ) { - - /* setup the defaults */ - $content = ''; - $installed = false; - $links = array(); - $current_stylesheet = get_stylesheet(); - $latest_version = $theme->version; - $item_id = $theme->item_id; - $template = ''; - $stylesheet = ''; - $title = $theme->theme_name; - $version = ''; - $description = $theme->description; - $author = $theme->author_name; - $parent_theme = ''; - $tags = ''; - - /* setup the item details */ - $item_details = $this->protected_api->item_details( $item_id ); - - if ( ! empty( $item_details ) ) { - - /* get installed theme information */ - foreach( $get_themes as $k => $v ) { - if ( $get_themes[$k]['Title'] == $title && $get_themes[$k]['Author Name'] == $author && $template == '' ) { - $template = $get_themes[$k]['Template']; - $stylesheet = $get_themes[$k]['Stylesheet']; - $title = $get_themes[$k]['Title']; - $version = $get_themes[$k]['Version']; - $description = $get_themes[$k]['Description']; - $author = $get_themes[$k]['Author']; - $screenshot = $get_themes[$k]['Screenshot']; - $stylesheet_dir = $get_themes[$k]['Stylesheet Dir']; - $template_dir = $get_themes[$k]['Template Dir']; - $parent_theme = $get_themes[$k]['Parent Theme']; - $theme_root = $get_themes[$k]['Theme Root']; - $theme_root_uri = $get_themes[$k]['Theme Root URI']; - $tags = $get_themes[$k]['Tags']; - $installed = true; - continue; - } - } - - $has_update = ( $installed && version_compare( $version, $latest_version, '<' ) ) ? TRUE : FALSE; - $details_url = htmlspecialchars( add_query_arg( array( 'TB_iframe' => 'true', 'width' => 1024, 'height' => 800 ), $item_details->url ) ); - $activate_url = wp_nonce_url( network_admin_url( 'admin.php?page=' . EWPT_PLUGIN_SLUG . '&action=activate&template=' . urlencode( $template ) . '&stylesheet=' . urlencode( $stylesheet ) ), 'switch-theme_' . $template ); - $preview_url = htmlspecialchars( add_query_arg( array( 'preview' => 1, 'template' => $template, 'stylesheet' => $stylesheet, 'preview_iframe' => 1, 'TB_iframe' => 'true' ), trailingslashit( esc_url( get_option( 'home' ) ) ) ) ); - $delete_url = wp_nonce_url( network_admin_url( 'admin.php?page=' . EWPT_PLUGIN_SLUG . '&action=delete&template=' . $stylesheet ), 'delete-theme_' . $stylesheet ); - $delete_onclick = 'onclick="if ( confirm(\'' . esc_js( sprintf( __( "You're about to delete the '%s' theme. 'Cancel' to stop, 'OK' to update.", 'envato-wordpress-toolkit' ), $title ) ) . '\') ) {return true;}return false;"'; - $install_url = wp_nonce_url( network_admin_url( 'admin.php?page=' . EWPT_PLUGIN_SLUG . '&action=install-theme&theme=' . $item_id ), 'install-theme_' . $item_id ); - $update_url = wp_nonce_url( network_admin_url( 'admin.php?page=' . EWPT_PLUGIN_SLUG . '&action=upgrade-theme&theme=' . $stylesheet . '&item_id=' . $item_id ), 'upgrade-theme_' . $stylesheet ); - $update_onclick = 'onclick="if ( confirm(\'' . esc_js( __( "Updating this theme will lose any customizations you have made. 'Cancel' to stop, 'OK' to update.", 'envato-wordpress-toolkit' ) ) . '\') ) {return true;}return false;"'; + /* get WP installed themes */ + if ( function_exists( 'wp_get_themes' ) ) + $get_themes = wp_get_themes(); + else + $get_themes = get_themes(); + + /* empty premium themes array */ + $premium_themes = array(); + + /* loop through the marketplace themes */ + if ( ! empty( $themes ) && is_array( $themes ) ) { + foreach( $themes as $theme ) { - /* Theme Title message */ - $content.= '

' . $title . ' ' . $version . ' by ' . $author . '

'; - - /* Theme Description */ - if ( $description ) { - $content.= '

' . $description . '

'; - } + /* setup the defaults */ + $content = ''; + $installed = false; + $links = array(); + $current_stylesheet = get_stylesheet(); + $latest_version = $theme->version; + $item_id = $theme->item_id; + $template = ''; + $stylesheet = ''; + $title = $theme->theme_name; + $version = ''; + $description = $theme->description; + $author = $theme->author_name; + $parent_theme = ''; + $tags = ''; + + /* setup the item details */ + $item_details = $this->protected_api->item_details( $item_id ); - /* Theme Backup URI */ - $theme_backup_uri = $this->_get_theme_backup_uri( $template ); + if ( ! empty( $item_details ) ) { - /* Links list */ - if ( $stylesheet && $template && $current_stylesheet !== $stylesheet ) { + /* get installed theme information */ + foreach( $get_themes as $k => $v ) { + if ( $get_themes[$k]['Title'] == $title && $get_themes[$k]['Author Name'] == $author && $template == '' ) { + $template = $get_themes[$k]['Template']; + $stylesheet = $get_themes[$k]['Stylesheet']; + $title = $get_themes[$k]['Title']; + $version = $get_themes[$k]['Version']; + $description = $get_themes[$k]['Description']; + $author = $get_themes[$k]['Author']; + $screenshot = $get_themes[$k]['Screenshot']; + $stylesheet_dir = $get_themes[$k]['Stylesheet Dir']; + $template_dir = $get_themes[$k]['Template Dir']; + $parent_theme = $get_themes[$k]['Parent Theme']; + $theme_root = $get_themes[$k]['Theme Root']; + $theme_root_uri = $get_themes[$k]['Theme Root URI']; + $tags = $get_themes[$k]['Tags']; + $installed = true; + continue; + } + } + + $has_update = ( $installed && version_compare( $version, $latest_version, '<' ) ) ? TRUE : FALSE; + $details_url = htmlspecialchars( add_query_arg( array( 'TB_iframe' => 'true', 'width' => 1024, 'height' => 800 ), $item_details->url ) ); + $activate_url = wp_nonce_url( network_admin_url( 'admin.php?page=' . EWPT_PLUGIN_SLUG . '&action=activate&template=' . urlencode( $template ) . '&stylesheet=' . urlencode( $stylesheet ) ), 'switch-theme_' . $template ); + $preview_url = htmlspecialchars( add_query_arg( array( 'preview' => 1, 'template' => $template, 'stylesheet' => $stylesheet, 'preview_iframe' => 1, 'TB_iframe' => 'true' ), trailingslashit( esc_url( get_option( 'home' ) ) ) ) ); + $delete_url = wp_nonce_url( network_admin_url( 'admin.php?page=' . EWPT_PLUGIN_SLUG . '&action=delete&template=' . $stylesheet ), 'delete-theme_' . $stylesheet ); + $delete_onclick = 'onclick="if ( confirm(\'' . esc_js( sprintf( __( "You're about to delete the '%s' theme. 'Cancel' to stop, 'OK' to update.", 'envato-wordpress-toolkit' ), $title ) ) . '\') ) {return true;}return false;"'; + $install_url = wp_nonce_url( network_admin_url( 'admin.php?page=' . EWPT_PLUGIN_SLUG . '&action=install-theme&theme=' . $item_id ), 'install-theme_' . $item_id ); + $update_url = wp_nonce_url( network_admin_url( 'admin.php?page=' . EWPT_PLUGIN_SLUG . '&action=upgrade-theme&theme=' . $stylesheet . '&item_id=' . $item_id ), 'upgrade-theme_' . $stylesheet ); + $update_onclick = 'onclick="if ( confirm(\'' . esc_js( __( "Updating this theme will lose any customizations you have made. 'Cancel' to stop, 'OK' to update.", 'envato-wordpress-toolkit' ) ) . '\') ) {return true;}return false;"'; - $links[] = '' . __( 'Activate', 'envato-wordpress-toolkit' ) . ' |'; + /* Theme Title message */ + $content.= '

' . $title . ' ' . $version . ' by ' . $author . '

'; + + /* Theme Description */ + if ( $description ) { + $content.= '

' . $description . '

'; + } + + /* Theme Backup URI */ + $theme_backup_uri = $this->_get_theme_backup_uri( $template ); - $links[] = '' . __( 'Preview', 'envato-wordpress-toolkit' ) . ' |'; + /* Links list */ + if ( $stylesheet && $template && $current_stylesheet !== $stylesheet ) { + + $links[] = '' . __( 'Activate', 'envato-wordpress-toolkit' ) . ' |'; + + $links[] = '' . __( 'Preview', 'envato-wordpress-toolkit' ) . ' |'; + + $links[] = '' . __( 'Preview', 'envato-wordpress-toolkit' ) . ' |'; + + $links[] = '' . __( 'Delete' ) . ' |'; + + $links[] = '' . esc_attr( sprintf( __( 'View version %1$s details', 'envato-wordpress-toolkit' ), $latest_version ) ) . ' |'; + + if ( ! empty( $theme_backup_uri ) ) { + $links[] = '' . esc_attr( __( 'Download Backup', 'envato-wordpress-toolkit' ) ) . ' |'; + } + + $content.= '
' . rtrim( implode( ' ', $links ), ' |' ) . '
'; + + } - $links[] = '' . __( 'Preview', 'envato-wordpress-toolkit' ) . ' |'; + /** + * This ugly code lists the current theme options + * It was pulled from wp-admin/themes.php with minor tweaks + */ + if ( $current_stylesheet == $stylesheet ) { + global $self, $submenu; + $parent_file = 'themes.php'; + $options = array(); + if ( is_array( $submenu ) && isset( $submenu['themes.php'] ) ) { + foreach ( (array) $submenu['themes.php'] as $item) { + $class = ''; + if ( 'themes.php' == $item[2] || 'theme-editor.php' == $item[2] ) + continue; + // 0 = name, 1 = capability, 2 = file + if ( ( strcmp($self, $item[2]) == 0 && empty($parent_file)) || ($parent_file && ($item[2] == $parent_file)) ) + $class = ' class="current"'; + if ( !empty($submenu[$item[2]]) ) { + $submenu[$item[2]] = array_values($submenu[$item[2]]); // Re-index. + $menu_hook = get_plugin_page_hook($submenu[$item[2]][0][2], $item[2]); + if ( file_exists(WP_PLUGIN_DIR . "/{$submenu[$item[2]][0][2]}") || !empty($menu_hook)) + $options[] = "{$item[0]}"; + else + $options[] = "{$item[0]}"; + } else if ( current_user_can($item[1]) ) { + $menu_file = $item[2]; + if ( false !== ( $pos = strpos( $menu_file, '?' ) ) ) + $menu_file = substr( $menu_file, 0, $pos ); + if ( file_exists( ABSPATH . "wp-admin/$menu_file" ) ) { + $options[] = "{$item[0]}"; + } else { + $options[] = "{$item[0]}"; + } + } + } + } + + if ( ! empty( $theme_backup_uri ) ) { + $options[] = '' . esc_attr( __( 'Download Backup', 'envato-wordpress-toolkit' ) ) . ''; + } + if ( ! empty( $options ) ) + $content.= '
' . __( 'Options:', 'envato-wordpress-toolkit' ) . ' ' . implode( ' | ', $options ) . '
'; + } - $links[] = '' . __( 'Delete' ) . ' |'; + /* Theme path information */ + if ( current_user_can( 'edit_themes' ) && $installed ) { + if ( $parent_theme ) { + $content.= '

' . sprintf( __( 'The template files are located in %2$s. The stylesheet files are located in %3$s. %4$s uses templates from %5$s. Changes made to the templates will affect both themes.', 'envato-wordpress-toolkit' ), $title, str_replace( WP_CONTENT_DIR, '', $template_dir ), str_replace( WP_CONTENT_DIR, '', $stylesheet_dir ), $title, $parent_theme ) . '

'; + } else { + $content.= '

' . sprintf( __( 'All of this theme’s files are located in %2$s.', 'envato-wordpress-toolkit' ), $title, str_replace( WP_CONTENT_DIR, '', $template_dir ), str_replace( WP_CONTENT_DIR, '', $stylesheet_dir ) ) . '

'; + } + } - $links[] = '' . esc_attr( sprintf( __( 'View version %1$s details', 'envato-wordpress-toolkit' ), $latest_version ) ) . ' |'; + /* Tags list */ + if ( $tags ) { + $content.= '

' . __( 'Tags: ' ). join( ', ', $tags ) . '

'; + } - if ( ! empty( $theme_backup_uri ) ) { - $links[] = '' . esc_attr( __( 'Download Backup', 'envato-wordpress-toolkit' ) ) . ' |'; + /* Upgrade/Install message */ + if ( $has_update ) { + if ( ! current_user_can( 'update_themes' ) ) { + $content.= sprintf( '

' . __( 'There is a new version of %1$s available. View version %3$s details.', 'envato-wordpress-toolkit' ) . '

', $title, $details_url, $latest_version ); + } else { + $content.= sprintf( '

' . __( 'There is a new version of %1$s available. View version %3$s details or update automatically.', 'envato-wordpress-toolkit' ) . '

', $title, $details_url, $latest_version, $update_url, $update_onclick ); + } + } else if ( ! $installed ) { + if ( ! current_user_can( 'update_themes' ) ) { + $content.= sprintf( '

' . __( '%1$s has not been installed. View version %3$s details.', 'envato-wordpress-toolkit' ) . '

', $title, $details_url, $latest_version ); + } else { + $content.= sprintf( '

' . __( '%1$s has not been installed. View version %3$s details or install automatically.', 'envato-wordpress-toolkit' ) . '

', $title, $details_url, $latest_version, $install_url ); + } } - $content.= '
' . rtrim( implode( ' ', $links ), ' |' ) . '
'; + /* put the HTML into a variable */ + $list_item = ' +
  • +
    + ' . $title . ' +
    +
    + ' . $content . ' +
    +
  • '; + $premium_themes[] = array( + 'current_theme' => ( $current_stylesheet == $stylesheet ? true : false ), + 'list_item' => $list_item + ); + } - /** - * This ugly code lists the current theme options - * It was pulled from wp-admin/themes.php with minor tweaks - */ - if ( $current_stylesheet == $stylesheet ) { - global $self, $submenu; - $parent_file = 'themes.php'; - $options = array(); - if ( is_array( $submenu ) && isset( $submenu['themes.php'] ) ) { - foreach ( (array) $submenu['themes.php'] as $item) { - $class = ''; - if ( 'themes.php' == $item[2] || 'theme-editor.php' == $item[2] ) - continue; - // 0 = name, 1 = capability, 2 = file - if ( ( strcmp($self, $item[2]) == 0 && empty($parent_file)) || ($parent_file && ($item[2] == $parent_file)) ) - $class = ' class="current"'; - if ( !empty($submenu[$item[2]]) ) { - $submenu[$item[2]] = array_values($submenu[$item[2]]); // Re-index. - $menu_hook = get_plugin_page_hook($submenu[$item[2]][0][2], $item[2]); - if ( file_exists(WP_PLUGIN_DIR . "/{$submenu[$item[2]][0][2]}") || !empty($menu_hook)) - $options[] = "{$item[0]}"; - else - $options[] = "{$item[0]}"; - } else if ( current_user_can($item[1]) ) { - $menu_file = $item[2]; - if ( false !== ( $pos = strpos( $menu_file, '?' ) ) ) - $menu_file = substr( $menu_file, 0, $pos ); - if ( file_exists( ABSPATH . "wp-admin/$menu_file" ) ) { - $options[] = "{$item[0]}"; - } else { - $options[] = "{$item[0]}"; - } - } - } - } - - if ( ! empty( $theme_backup_uri ) ) { - $options[] = '' . esc_attr( __( 'Download Backup', 'envato-wordpress-toolkit' ) ) . ''; - } - if ( ! empty( $options ) ) - $content.= '
    ' . __( 'Options:', 'envato-wordpress-toolkit' ) . ' ' . implode( ' | ', $options ) . '
    '; + } + } + + /** + * Loop through all the premium themes. + * Separate out the current one, display it, & remove from array + * Display the other premium themes after edits to the array. + */ + if ( ! empty( $premium_themes ) ) { + $themes_output = ''; + $current_theme = array(); + foreach ( $premium_themes as $k => $v ) { + if ( $premium_themes[$k]['current_theme'] == true ) { + $current_theme = $premium_themes[$k]; + unset( $premium_themes[$k] ); } - - /* Theme path information */ - if ( current_user_can( 'edit_themes' ) && $installed ) { - if ( $parent_theme ) { - $content.= '

    ' . sprintf( __( 'The template files are located in %2$s. The stylesheet files are located in %3$s. %4$s uses templates from %5$s. Changes made to the templates will affect both themes.', 'envato-wordpress-toolkit' ), $title, str_replace( WP_CONTENT_DIR, '', $template_dir ), str_replace( WP_CONTENT_DIR, '', $stylesheet_dir ), $title, $parent_theme ) . '

    '; - } else { - $content.= '

    ' . sprintf( __( 'All of this theme’s files are located in %2$s.', 'envato-wordpress-toolkit' ), $title, str_replace( WP_CONTENT_DIR, '', $template_dir ), str_replace( WP_CONTENT_DIR, '', $stylesheet_dir ) ) . '

    '; - } - } - - /* Tags list */ - if ( $tags ) { - $content.= '

    ' . __( 'Tags: ' ). join( ', ', $tags ) . '

    '; - } - - /* Upgrade/Install message */ - if ( $has_update ) { - if ( ! current_user_can( 'update_themes' ) ) { - $content.= sprintf( '

    ' . __( 'There is a new version of %1$s available. View version %3$s details.', 'envato-wordpress-toolkit' ) . '

    ', $title, $details_url, $latest_version ); - } else { - $content.= sprintf( '

    ' . __( 'There is a new version of %1$s available. View version %3$s details or update automatically.', 'envato-wordpress-toolkit' ) . '

    ', $title, $details_url, $latest_version, $update_url, $update_onclick ); - } - } else if ( ! $installed ) { - if ( ! current_user_can( 'update_themes' ) ) { - $content.= sprintf( '

    ' . __( '%1$s has not been installed. View version %3$s details.', 'envato-wordpress-toolkit' ) . '

    ', $title, $details_url, $latest_version ); - } else { - $content.= sprintf( '

    ' . __( '%1$s has not been installed. View version %3$s details or install automatically.', 'envato-wordpress-toolkit' ) . '

    ', $title, $details_url, $latest_version, $install_url ); - } - } - - /* put the HTML into a variable */ - $list_item = ' -
  • -
    - ' . $title . ' -
    -
    - ' . $content . ' -
    -
  • '; - - $premium_themes[] = array( - 'current_theme' => ( $current_stylesheet == $stylesheet ? true : false ), - 'list_item' => $list_item - ); - } - } - } - - /** - * Loop through all the premium themes. - * Separate out the current one, display it, & remove from array - * Display the other premium themes after edits to the array. - */ - if ( ! empty( $premium_themes ) ) { - $themes_output = ''; - $current_theme = array(); - foreach ( $premium_themes as $k => $v ) { - if ( $premium_themes[$k]['current_theme'] == true ) { - $current_theme = $premium_themes[$k]; - unset( $premium_themes[$k] ); + /* list current premium theme */ + if ( ! empty( $current_theme ) ) { + $themes_output.= __( '

    Current Theme

    ' ); + $themes_output.= '
      '; + $themes_output.= $current_theme['list_item']; + $themes_output.= '
    '; } - } - - /* list current premium theme */ - if ( ! empty( $current_theme ) ) { - $themes_output.= __( '

    Current Theme

    ' ); + + /* list premium themes */ + $themes_output.= __( '

    Available Themes

    ' ); $themes_output.= '
      '; - $themes_output.= $current_theme['list_item']; + foreach ( $premium_themes as $k => $v ) + $themes_output.= $premium_themes[$k]['list_item']; $themes_output.= '
    '; } - - /* list premium themes */ - $themes_output.= __( '

    Available Themes

    ' ); - $themes_output.= '
      '; - foreach ( $premium_themes as $k => $v ) - $themes_output.= $premium_themes[$k]['list_item']; - $themes_output.= '
    '; + } - - } - - /* Get the current tab */ - $tab = isset( $_GET['tab'] ) ? $_GET['tab'] : 'settings'; - /* Display Markup */ - echo '
    '; - - echo ''; - - if ( $tab == 'settings' || ! isset( $themes_output ) ) { - echo ' -
    '; - wp_nonce_field( 'update-options' ); - settings_fields( EWPT_PLUGIN_SLUG ); - do_settings_sections( EWPT_PLUGIN_SLUG ); - echo ' -

    - -

    -
    '; - } - - if ( $tab == 'themes' && isset( $themes_output ) ) { + echo ''; - } - - echo '
    '; - } - } - - /** - * Checks for updates to the plugin - * - * @access private - * @since 1.6 - * - * @return void - */ - protected function _admin_update_check() { - - if ( class_exists( 'WP_GitHub_Updater' ) ) { - - if ( is_admin() ) { // note the use of is_admin() to double check that this is happening in the admin - - $config = array( - 'slug' => plugin_basename( __FILE__ ), - 'proper_folder_name' => EWPT_PLUGIN_SLUG, - 'api_url' => 'https://api.github.com/repos/envato/' . EWPT_PLUGIN_SLUG, - 'raw_url' => 'https://raw.github.com/envato/' . EWPT_PLUGIN_SLUG . '/master', - 'github_url' => 'https://github.com/envato/' . EWPT_PLUGIN_SLUG, - 'zip_url' => 'https://github.com/envato/' . EWPT_PLUGIN_SLUG . '/archive/master.zip', - 'sslverify' => true, - 'requires' => '3.6', - 'tested' => '4.1', - 'readme' => 'readme.txt', - 'access_token' => '', - ); - - new WP_GitHub_Updater( $config ); - - } - - } - - } - - /** - * Runs code before the headers are sent - * - * @access private - * @since 1.0 - * - * @return void - */ - protected function _admin_init_before() { - - if ( isset( $_GET['page'] ) ) { - $page = $_GET['page']; - - /* only execute if this is the Envato WordPress Toolkit */ - if ( $page == EWPT_PLUGIN_SLUG ) { - - $this->_prepare_envato_backup(); - - /* adds thickbox for previews */ - add_thickbox(); - - /* action must be set and template or stylesheet */ - if ( isset( $_GET['action'] ) && ( isset( $_GET['template'] ) || isset( $_GET['stylesheet'] ) ) ) { - - /* get request variables */ - $action = $_GET['action']; - $template = isset( $_GET['template'] ) ? $_GET['template'] : ''; - $stylesheet = isset( $_GET['stylesheet'] ) ? $_GET['stylesheet'] : ''; - - /* required to use the switch_theme() & delete_theme() functions */ - include_once( ABSPATH . 'wp-admin/includes/theme.php' ); + if ( $tab == 'settings' || ! isset( $themes_output ) ) { + echo ' +
    '; + wp_nonce_field( 'update-options' ); + settings_fields( EWPT_PLUGIN_SLUG ); + do_settings_sections( EWPT_PLUGIN_SLUG ); + echo ' +

    + +

    +
    '; + } - if ( 'activate' == $action ) { - $this->_activate_theme( $template, $stylesheet ); - } else if ( 'delete' == $action ) { - $this->_delete_theme( $template ); + if ( $tab == 'themes' && isset( $themes_output ) ) { + + echo $themes_output; + } - } + + echo ''; } - } - } + } - /** - * Registers the settings for the updater - * - * @access private - * @since 1.0 - * - * @return void - */ - public function _admin_init() { - $this->_admin_update_check(); - $this->_admin_init_before(); - register_setting( EWPT_PLUGIN_SLUG, EWPT_PLUGIN_SLUG ); - add_settings_section( 'user_account_info', __( 'User Account Information', 'envato-wordpress-toolkit' ), array( $this, '_section_user_account_info' ), EWPT_PLUGIN_SLUG ); - add_settings_field( 'user_name', __( 'Marketplace Username', 'envato-wordpress-toolkit' ), array( $this, '_field_user_name' ), EWPT_PLUGIN_SLUG, 'user_account_info' ); - add_settings_field( 'api_key', __( 'Secret API Key', 'envato-wordpress-toolkit' ), array( $this, '_field_api_key' ), EWPT_PLUGIN_SLUG, 'user_account_info' ); - add_settings_section( 'backup_info', __( 'Backup Information', 'envato-wordpress-toolkit' ), array( $this, '_section_backup_information' ), EWPT_PLUGIN_SLUG ); - add_settings_field( 'skip_theme_backup', __( 'Skip Theme Backup', 'envato-wordpress-toolkit' ), array( $this, '_field_skip_theme_backup' ), EWPT_PLUGIN_SLUG, 'backup_info' ); - add_settings_section( 'github_updater', __( 'Github Updater', 'envato-wordpress-toolkit' ), array( $this, '_section_github_updater' ), EWPT_PLUGIN_SLUG ); - add_settings_field( 'deactivate_github_updater', __( 'Deactivate Github Updater', 'envato-wordpress-toolkit' ), array( $this, '_field_deactivate_github_updater' ), EWPT_PLUGIN_SLUG, 'github_updater' ); - } + /** + * Checks for updates to the plugin + * + * @access private + * @since 1.6 + * + * @return void + */ + protected function _admin_update_check() { - /** - * User account description - * - * @access private - * @since 1.0 - * - * @return string - */ - public function _section_user_account_info() { - _e( 'To obtain your API Key, visit your "My Settings" page on any of the Envato Marketplaces. Once a valid connection has been made any changes to the API key below for this username will not effect the results for 5 minutes because they\'re cached in the database. If you have already made an API connection and just purchase a theme and it\'s not showing up, wait five minutes and refresh the page. If the theme is still not showing up, it\'s possible the author has not made it available for auto install yet.', 'envato-wordpress-toolkit' ); - } + if ( class_exists( 'WP_GitHub_Updater' ) ) { - /** - * Username text field - * - * @access private - * @since 1.0 - * - * @return string - */ - public function _field_user_name() { - $options = get_option( EWPT_PLUGIN_SLUG ); - echo ''; - } + if ( is_admin() ) { // note the use of is_admin() to double check that this is happening in the admin - /** - * API Key text field - * - * @access private - * @since 1.0 - * - * @return string - */ - public function _field_api_key() { - $options = get_option( EWPT_PLUGIN_SLUG ); - echo ''; - } + $config = array( + 'slug' => plugin_basename( __FILE__ ), + 'proper_folder_name' => EWPT_PLUGIN_SLUG, + 'api_url' => 'https://api.github.com/repos/envato/' . EWPT_PLUGIN_SLUG, + 'raw_url' => 'https://raw.github.com/envato/' . EWPT_PLUGIN_SLUG . '/master', + 'github_url' => 'https://github.com/envato/' . EWPT_PLUGIN_SLUG, + 'zip_url' => 'https://github.com/envato/' . EWPT_PLUGIN_SLUG . '/archive/master.zip', + 'sslverify' => true, + 'requires' => '3.6', + 'tested' => '4.1', + 'readme' => 'readme.txt', + 'access_token' => '', + ); - /** - * Backup description - * - * @access private - * @since 1.0 - * - * @return string - */ - public function _section_backup_information() { - _e( 'This plugin will automatically save your theme as a ZIP archive before it does an upgrade. The directory those backups get saved to is wp-content/envato-backups. However, if you\'re experiencing problems while attempting to upgrade, it\'s likely to be a permissions issue and you may want to manually backup your theme before upgrading. Alternatively, if you don\'t want to backup your theme you can check the box below.', 'envato-wordpress-toolkit' ); - } + new WP_GitHub_Updater( $config ); - /** - * No theme backup - * - * @access private - * @since 1.0 - * - * @return string - */ - public function _field_skip_theme_backup() { - $options = get_option( EWPT_PLUGIN_SLUG ); - $field_value = isset( $options['skip_theme_backup'] ) ? true : false; - echo ''; - } + } - /** - * Github Updater - * - * @access private - * @since 1.7.1 - * - * @return string - */ - public function _section_github_updater() { - printf( __( 'This option lets you deactivate the %s class, so it does not load. If you want to update the plugin in the future, just uncheck this option and the plugin will look for a new version on Github; check it and it stops looking.', 'envato-wordpress-toolkit' ), 'WP_GitHub_Updater' ); - } + } - /** - * Deactivate Github Updater - * - * @access private - * @since 1.7.1 - * - * @return string - */ - public function _field_deactivate_github_updater() { - $options = get_option( EWPT_PLUGIN_SLUG ); - $field_value = isset( $options['deactivate_github_updater'] ) ? true : false; - echo ''; - } + } + + /** + * Runs code before the headers are sent + * + * @access private + * @since 1.0 + * + * @return void + */ + protected function _admin_init_before() { - /** - * Change the text on the install or upgrade screen - * - * @access private - * @since 1.0 - * - * @return array - */ - public function _complete_actions( $actions ) { - if ( isset( $_GET['page'] ) && isset( $_GET['action'] ) ) { - $page = $_GET['page']; - $action = $_GET['action']; - if ( $page == EWPT_PLUGIN_SLUG ) { - if ( 'install-theme' == $action || 'upgrade-theme' == $action ) { - $actions['themes_page'] = '' . sprintf( __( 'Return to %s', 'envato-wordpress-toolkit' ), EWPT_PLUGIN_NAME ) . ''; + if ( isset( $_GET['page'] ) ) { + $page = $_GET['page']; + + /* only execute if this is the Envato WordPress Toolkit */ + if ( $page == EWPT_PLUGIN_SLUG ) { + + $this->_prepare_envato_backup(); + + /* adds thickbox for previews */ + add_thickbox(); + + /* action must be set and template or stylesheet */ + if ( isset( $_GET['action'] ) && ( isset( $_GET['template'] ) || isset( $_GET['stylesheet'] ) ) ) { + + /* get request variables */ + $action = $_GET['action']; + $template = isset( $_GET['template'] ) ? $_GET['template'] : ''; + $stylesheet = isset( $_GET['stylesheet'] ) ? $_GET['stylesheet'] : ''; + + /* required to use the switch_theme() & delete_theme() functions */ + include_once( ABSPATH . 'wp-admin/includes/theme.php' ); + + if ( 'activate' == $action ) { + $this->_activate_theme( $template, $stylesheet ); + } else if ( 'delete' == $action ) { + $this->_delete_theme( $template ); + } + } } - } + } } - return $actions; - } - - - /** - * Manually installs a theme from the Envato API. - * - * @access private - * @since 1.0 - * @updated 1.1 - * - * @param string Theme item_id from ThemeForests - * @param array List of all purchased themes - * @return void - */ - protected function _install_theme( $theme, $themes ) { - global $current_screen; - check_admin_referer( 'install-theme_' . $theme ); - - if ( ! current_user_can( 'install_themes' ) ) - wp_die( __( 'You do not have sufficient permissions to install themes for this site.', 'envato-wordpress-toolkit' ) ); - - /* setup theme info in $api array */ - $api = (object) array(); - foreach( $themes as $t ) { - if ( $theme == $t->item_id ) { - $api->name = $t->item_name; - $api->version = $t->version; - continue; - } + /** + * Registers the settings for the updater + * + * @access private + * @since 1.0 + * + * @return void + */ + public function _admin_init() { + $this->_admin_update_check(); + $this->_admin_init_before(); + register_setting( EWPT_PLUGIN_SLUG, EWPT_PLUGIN_SLUG ); + add_settings_section( 'user_account_info', __( 'User Account Information', 'envato-wordpress-toolkit' ), array( $this, '_section_user_account_info' ), EWPT_PLUGIN_SLUG ); + add_settings_field( 'user_name', __( 'Marketplace Username', 'envato-wordpress-toolkit' ), array( $this, '_field_user_name' ), EWPT_PLUGIN_SLUG, 'user_account_info' ); + add_settings_field( 'api_key', __( 'Secret API Key', 'envato-wordpress-toolkit' ), array( $this, '_field_api_key' ), EWPT_PLUGIN_SLUG, 'user_account_info' ); + add_settings_section( 'backup_info', __( 'Backup Information', 'envato-wordpress-toolkit' ), array( $this, '_section_backup_information' ), EWPT_PLUGIN_SLUG ); + add_settings_field( 'skip_theme_backup', __( 'Skip Theme Backup', 'envato-wordpress-toolkit' ), array( $this, '_field_skip_theme_backup' ), EWPT_PLUGIN_SLUG, 'backup_info' ); + add_settings_section( 'github_updater', __( 'Github Updater', 'envato-wordpress-toolkit' ), array( $this, '_section_github_updater' ), EWPT_PLUGIN_SLUG ); + add_settings_field( 'deactivate_github_updater', __( 'Deactivate Github Updater', 'envato-wordpress-toolkit' ), array( $this, '_field_deactivate_github_updater' ), EWPT_PLUGIN_SLUG, 'github_updater' ); } - $title = sprintf( __( 'Installing Theme: %s', 'envato-wordpress-toolkit' ), $api->name . ' ' . $api->version ); - $nonce = 'install-theme_' . $theme; - $url = network_admin_url( 'admin.php?page=' . EWPT_PLUGIN_SLUG . '&action=install-theme&theme=' . $theme ); - $type = 'web'; - - /* trick WP into thinking it's the themes page for the icon32 */ - $current_screen->parent_base = 'themes'; + /** + * User account description + * + * @access private + * @since 1.0 + * + * @return string + */ + public function _section_user_account_info() { + _e( 'To obtain your API Key, visit your "My Settings" page on any of the Envato Marketplaces. Once a valid connection has been made any changes to the API key below for this username will not effect the results for 5 minutes because they\'re cached in the database. If you have already made an API connection and just purchase a theme and it\'s not showing up, wait five minutes and refresh the page. If the theme is still not showing up, it\'s possible the author has not made it available for auto install yet.', 'envato-wordpress-toolkit' ); + } - /* new Envato_Theme_Upgrader */ - $upgrader = new Envato_Theme_Upgrader( new Theme_Installer_Skin( compact( 'title', 'url', 'api', 'nonce' ) ) ); + /** + * Username text field + * + * @access private + * @since 1.0 + * + * @return string + */ + public function _field_user_name() { + $options = get_option( EWPT_PLUGIN_SLUG ); + echo ''; + } - /* install the theme */ - $upgrader->install( $this->protected_api->wp_download( $theme ) ); - } - - /** - * Activate an Envato theme - * - * @access private - * @since 1.0 - * - * @param string Template name - * @param array Stylesheet name - * @return void - */ - protected function _activate_theme( $template, $stylesheet ) { - check_admin_referer( 'switch-theme_' . $template ); + /** + * API Key text field + * + * @access private + * @since 1.0 + * + * @return string + */ + public function _field_api_key() { + $options = get_option( EWPT_PLUGIN_SLUG ); + echo ''; + } - if ( ! current_user_can( 'switch_themes' ) && ! current_user_can( 'edit_theme_options' ) ) - wp_die( __( 'You do not have sufficient permissions to update themes for this site.', 'envato-wordpress-toolkit' ) ); + /** + * Backup description + * + * @access private + * @since 1.0 + * + * @return string + */ + public function _section_backup_information() { + _e( 'This plugin will automatically save your theme as a ZIP archive before it does an upgrade. The directory those backups get saved to is wp-content/envato-backups. However, if you\'re experiencing problems while attempting to upgrade, it\'s likely to be a permissions issue and you may want to manually backup your theme before upgrading. Alternatively, if you don\'t want to backup your theme you can check the box below.', 'envato-wordpress-toolkit' ); + } - if ( ! function_exists( 'switch_theme' ) ) - include_once( ABSPATH . 'wp-admin/includes/theme.php' ); - - switch_theme( $template, $stylesheet ); - wp_redirect( network_admin_url( 'admin.php?page=' . EWPT_PLUGIN_SLUG . '&activated=true&tab=themes' ) ); - exit; - } - - /** - * Manually upgrades a theme from the Envato API. - * - * @access private - * @since 1.0 - * @updated 1.1 - * - * @param string Theme slug - * @param string Theme item_id from ThemeForests - * @return void - */ - protected function _upgrade_theme( $theme, $item_id ) { - global $current_screen; + /** + * No theme backup + * + * @access private + * @since 1.0 + * + * @return string + */ + public function _field_skip_theme_backup() { + $options = get_option( EWPT_PLUGIN_SLUG ); + $field_value = isset( $options['skip_theme_backup'] ) ? true : false; + echo ''; + } - check_admin_referer( 'upgrade-theme_' . $theme ); + /** + * Github Updater + * + * @access private + * @since 1.7.1 + * + * @return string + */ + public function _section_github_updater() { + printf( __( 'This option lets you deactivate the %s class, so it does not load. If you want to update the plugin in the future, just uncheck this option and the plugin will look for a new version on Github; check it and it stops looking.', 'envato-wordpress-toolkit' ), 'WP_GitHub_Updater' ); + } - if ( ! current_user_can( 'update_themes' ) ) - wp_die( __( 'You do not have sufficient permissions to update themes for this site.', 'envato-wordpress-toolkit' ) ); + /** + * Deactivate Github Updater + * + * @access private + * @since 1.7.1 + * + * @return string + */ + public function _field_deactivate_github_updater() { + $options = get_option( EWPT_PLUGIN_SLUG ); + $field_value = isset( $options['deactivate_github_updater'] ) ? true : false; + echo ''; + } - $title = __( 'Update Theme', 'envato-wordpress-toolkit' ); - $nonce = 'upgrade-theme_' . $theme; - $url = network_admin_url( 'admin.php?page=' . EWPT_PLUGIN_SLUG . '&action=upgrade-theme&tab=themes&theme=' . $theme . '&item_id=' . $item_id ); + /** + * Change the text on the install or upgrade screen + * + * @access private + * @since 1.0 + * + * @return array + */ + public function _complete_actions( $actions ) { + if ( isset( $_GET['page'] ) && isset( $_GET['action'] ) ) { + $page = $_GET['page']; + $action = $_GET['action']; + if ( $page == EWPT_PLUGIN_SLUG ) { + if ( 'install-theme' == $action || 'upgrade-theme' == $action ) { + $actions['themes_page'] = '' . sprintf( __( 'Return to %s', 'envato-wordpress-toolkit' ), EWPT_PLUGIN_NAME ) . ''; + } + } + } + return $actions; + } - /* trick WP into thinking it's the themes page for the icon32 */ - $current_screen->parent_base = 'themes'; - /* Upgrade Theme if a backup is created first */ - $options = get_option( EWPT_PLUGIN_SLUG ); - if ( isset( $options['skip_theme_backup'] ) || $this->_backup_theme( $theme ) === true ) { + /** + * Manually installs a theme from the Envato API. + * + * @access private + * @since 1.0 + * @updated 1.1 + * + * @param string Theme item_id from ThemeForests + * @param array List of all purchased themes + * @return void + */ + protected function _install_theme( $theme, $themes ) { + global $current_screen; + + check_admin_referer( 'install-theme_' . $theme ); + + if ( ! current_user_can( 'install_themes' ) ) + wp_die( __( 'You do not have sufficient permissions to install themes for this site.', 'envato-wordpress-toolkit' ) ); + + /* setup theme info in $api array */ + $api = (object) array(); + foreach( $themes as $t ) { + if ( $theme == $t->item_id ) { + $api->name = $t->item_name; + $api->version = $t->version; + continue; + } + } + + $title = sprintf( __( 'Installing Theme: %s', 'envato-wordpress-toolkit' ), $api->name . ' ' . $api->version ); + $nonce = 'install-theme_' . $theme; + $url = network_admin_url( 'admin.php?page=' . EWPT_PLUGIN_SLUG . '&action=install-theme&theme=' . $theme ); + $type = 'web'; + + /* trick WP into thinking it's the themes page for the icon32 */ + $current_screen->parent_base = 'themes'; + /* new Envato_Theme_Upgrader */ - $upgrader = new Envato_Theme_Upgrader( new Theme_Upgrader_Skin( compact( 'title', 'nonce', 'url', 'theme' ) ) ); + $upgrader = new Envato_Theme_Upgrader( new Theme_Installer_Skin( compact( 'title', 'url', 'api', 'nonce' ) ) ); - /* upgrade the theme */ - $upgrader->upgrade( $theme, $this->protected_api->wp_download( $item_id ) ); + /* install the theme */ + $upgrader->install( $this->protected_api->wp_download( $theme ) ); } - } - - /** - * Delete an Envato theme - * - * @access private - * @since 1.0 - * - * @param string Template name - * @return void - */ - protected function _delete_theme( $template ) { - check_admin_referer( 'delete-theme_' . $template ); - - if ( ! current_user_can( 'switch_themes' ) && ! current_user_can( 'edit_theme_options' ) ) - wp_die( __( 'You do not have sufficient permissions to update themes for this site.', 'envato-wordpress-toolkit' ) ); - - if ( ! current_user_can( 'delete_themes' ) ) - wp_die( __( 'You do not have sufficient permissions to delete themes for this site.', 'envato-wordpress-toolkit' ) ); - - if ( ! function_exists( 'delete_theme' ) ) - include_once( ABSPATH . 'wp-admin/includes/theme.php' ); - - delete_theme( $template, wp_nonce_url( network_admin_url( 'admin.php?page=' . EWPT_PLUGIN_SLUG . '&action=delete&template=' . $template ), 'delete-theme_' . $template ) ); - wp_redirect( network_admin_url( 'admin.php?page=' . EWPT_PLUGIN_SLUG . '&deleted=true&tab=themes' ) ); - exit; - } - - /** - * Backup an Envato theme. - * - * This function requires the template/theme slug - * to locate and backup that theme. - * - * @access private - * @since 1.4 - * - * @param string Template slug - * @return void - */ - protected function _backup_theme( $theme ) { - - $backup_errors = array(); - - $theme_backup = Envato_Backup::get_instance(); - - $theme_backup->path = EWPT_BACKUP_DIR; - $theme_backup->root = get_theme_root() . '/' . $theme . '/'; - - $theme_backup->archive_filename = strtolower( sanitize_file_name( $theme . '.backup.' . date( 'Y-m-d-H-i-s', time() + ( current_time( 'timestamp' ) - time() ) ) . '.zip' ) ); - - if ( ( ! is_dir( $theme_backup->path() ) && ( ! is_writable( dirname( $theme_backup->path() ) ) || ! mkdir( $theme_backup->path() ) ) ) || ! is_writable( $theme_backup->path() ) ) { - array_push( $backup_errors, 'Invalid backup path' ); - return false; + /** + * Activate an Envato theme + * + * @access private + * @since 1.0 + * + * @param string Template name + * @param array Stylesheet name + * @return void + */ + protected function _activate_theme( $template, $stylesheet ) { + check_admin_referer( 'switch-theme_' . $template ); + + if ( ! current_user_can( 'switch_themes' ) && ! current_user_can( 'edit_theme_options' ) ) + wp_die( __( 'You do not have sufficient permissions to update themes for this site.', 'envato-wordpress-toolkit' ) ); + + if ( ! function_exists( 'switch_theme' ) ) + include_once( ABSPATH . 'wp-admin/includes/theme.php' ); + + switch_theme( $template, $stylesheet ); + wp_redirect( network_admin_url( 'admin.php?page=' . EWPT_PLUGIN_SLUG . '&activated=true&tab=themes' ) ); + exit; } - if ( ! is_dir( $theme_backup->root() ) || ! is_readable( $theme_backup->root() ) ) { - array_push( $backup_errors, 'Invalid root path' ); - return false; + /** + * Manually upgrades a theme from the Envato API. + * + * @access private + * @since 1.0 + * @updated 1.1 + * + * @param string Theme slug + * @param string Theme item_id from ThemeForests + * @return void + */ + protected function _upgrade_theme( $theme, $item_id ) { + global $current_screen; + + check_admin_referer( 'upgrade-theme_' . $theme ); + + if ( ! current_user_can( 'update_themes' ) ) + wp_die( __( 'You do not have sufficient permissions to update themes for this site.', 'envato-wordpress-toolkit' ) ); + + $title = __( 'Update Theme', 'envato-wordpress-toolkit' ); + $nonce = 'upgrade-theme_' . $theme; + $url = network_admin_url( 'admin.php?page=' . EWPT_PLUGIN_SLUG . '&action=upgrade-theme&tab=themes&theme=' . $theme . '&item_id=' . $item_id ); + + /* trick WP into thinking it's the themes page for the icon32 */ + $current_screen->parent_base = 'themes'; + + /* Upgrade Theme if a backup is created first */ + $options = get_option( EWPT_PLUGIN_SLUG ); + if ( isset( $options['skip_theme_backup'] ) || $this->_backup_theme( $theme ) === true ) { + /* new Envato_Theme_Upgrader */ + $upgrader = new Envato_Theme_Upgrader( new Theme_Upgrader_Skin( compact( 'title', 'nonce', 'url', 'theme' ) ) ); + + /* upgrade the theme */ + $upgrader->upgrade( $theme, $this->protected_api->wp_download( $item_id ) ); + } } - $theme_backup->backup(); - - if ( file_exists( Envato_Backup::get_instance()->archive_filepath() ) ) { - return true; - } else { - return $backup_errors; - } - } + /** + * Delete an Envato theme + * + * @access private + * @since 1.0 + * + * @param string Template name + * @return void + */ + protected function _delete_theme( $template ) { + check_admin_referer( 'delete-theme_' . $template ); - /** - * Prepare the envato backup directory and .htaccess - * - * @access private - * @since 1.4 - * - * @return void - */ - function _prepare_envato_backup() { - - $path = EWPT_BACKUP_DIR; - - /* Create the backups directory if it doesn't exist */ - if ( is_writable( dirname( $path ) ) && ! is_dir( $path ) ) - mkdir( $path, 0755 ); - - /* Secure the directory with a .htaccess file */ - $htaccess = $path . '.htaccess'; - - $contents[] = '# ' . __( 'This .htaccess file ensures that other people cannot download your backup files.', 'envato-wordpress-toolkit' ); - $contents[] = ''; - $contents[] = ''; - $contents[] = 'RewriteEngine On'; - $contents[] = 'RewriteCond %{QUERY_STRING} !key=' . md5( EWPT_SECURE_KEY ); - $contents[] = 'RewriteRule (.*) - [F]'; - $contents[] = ''; - $contents[] = ''; - - if ( ! file_exists( $htaccess ) && is_writable( $path ) && require_once( ABSPATH . '/wp-admin/includes/misc.php' ) ) - insert_with_markers( $htaccess, 'EnvatoBackup', $contents ); - - } - - /** - * Get the backup directory path for a given theme. - * - * @access private - * @since 1.4 - * - * @param string Theme slug. - * @return bool|string Return the theme path or false. - */ - protected function _get_theme_backup_dir( $theme ) { + if ( ! current_user_can( 'switch_themes' ) && ! current_user_can( 'edit_theme_options' ) ) + wp_die( __( 'You do not have sufficient permissions to update themes for this site.', 'envato-wordpress-toolkit' ) ); + + if ( ! current_user_can( 'delete_themes' ) ) + wp_die( __( 'You do not have sufficient permissions to delete themes for this site.', 'envato-wordpress-toolkit' ) ); + + if ( ! function_exists( 'delete_theme' ) ) + include_once( ABSPATH . 'wp-admin/includes/theme.php' ); + + delete_theme( $template, wp_nonce_url( network_admin_url( 'admin.php?page=' . EWPT_PLUGIN_SLUG . '&action=delete&template=' . $template ), 'delete-theme_' . $template ) ); + wp_redirect( network_admin_url( 'admin.php?page=' . EWPT_PLUGIN_SLUG . '&deleted=true&tab=themes' ) ); + exit; + } - $backup_path = EWPT_BACKUP_DIR; - - if ( $handle = @opendir( $backup_path ) ) { - $files = array(); - while ( false !== ( $file = readdir( $handle ) ) ) { - $exploded_file = explode( '.', $file ); - if ( reset( $exploded_file ) == $theme && end( $exploded_file ) == 'zip' ) { - $files[@filemtime( trailingslashit( $backup_path ) . $file )] = trailingslashit( $backup_path ) . $file; - } + /** + * Backup an Envato theme. + * + * This function requires the template/theme slug + * to locate and backup that theme. + * + * @access private + * @since 1.4 + * + * @param string Template slug + * @return void + */ + protected function _backup_theme( $theme ) { + + $backup_errors = array(); + + $theme_backup = Envato_Backup::get_instance(); + + $theme_backup->path = EWPT_BACKUP_DIR; + + $theme_backup->root = get_theme_root() . '/' . $theme . '/'; + + $theme_backup->archive_filename = strtolower( sanitize_file_name( $theme . '.backup.' . date( 'Y-m-d-H-i-s', time() + ( current_time( 'timestamp' ) - time() ) ) . '.zip' ) ); + + if ( ( ! is_dir( $theme_backup->path() ) && ( ! is_writable( dirname( $theme_backup->path() ) ) || ! mkdir( $theme_backup->path() ) ) ) || ! is_writable( $theme_backup->path() ) ) { + array_push( $backup_errors, 'Invalid backup path' ); + return false; + } + + if ( ! is_dir( $theme_backup->root() ) || ! is_readable( $theme_backup->root() ) ) { + array_push( $backup_errors, 'Invalid root path' ); + return false; + } + + $theme_backup->backup(); + + if ( file_exists( Envato_Backup::get_instance()->archive_filepath() ) ) { + return true; + } else { + return $backup_errors; } - closedir( $handle ); - krsort( $files ); } - if ( isset( $files ) && ! empty( $files ) ) - return array_shift( $files ); - - return false; - } + /** + * Prepare the envato backup directory and .htaccess + * + * @access private + * @since 1.4 + * + * @return void + */ + function _prepare_envato_backup() { + + $path = EWPT_BACKUP_DIR; + + /* Create the backups directory if it doesn't exist */ + if ( is_writable( dirname( $path ) ) && ! is_dir( $path ) ) + mkdir( $path, 0755 ); + + /* Secure the directory with a .htaccess file */ + $htaccess = $path . '.htaccess'; + + $contents[] = '# ' . __( 'This .htaccess file ensures that other people cannot download your backup files.', 'envato-wordpress-toolkit' ); + $contents[] = ''; + $contents[] = ''; + $contents[] = 'RewriteEngine On'; + $contents[] = 'RewriteCond %{QUERY_STRING} !key=' . md5( EWPT_SECURE_KEY ); + $contents[] = 'RewriteRule (.*) - [F]'; + $contents[] = ''; + $contents[] = ''; + + if ( ! file_exists( $htaccess ) && is_writable( $path ) && require_once( ABSPATH . '/wp-admin/includes/misc.php' ) ) + insert_with_markers( $htaccess, 'EnvatoBackup', $contents ); - /** - * Get the backup directory URI for a given theme. - * - * @uses _get_theme_backup_dir() - * - * @access private - * @since 1.4 - * - * @param string Theme slug. - * @return bool|string Return the theme URI or false. - */ - protected function _get_theme_backup_uri( $theme ) { + } - $theme_backup = $this->_get_theme_backup_dir( $theme ); + /** + * Get the backup directory path for a given theme. + * + * @access private + * @since 1.4 + * + * @param string Theme slug. + * @return bool|string Return the theme path or false. + */ + protected function _get_theme_backup_dir( $theme ) { - if ( empty( $theme_backup ) ) + $backup_path = EWPT_BACKUP_DIR; + + if ( $handle = @opendir( $backup_path ) ) { + $files = array(); + while ( false !== ( $file = readdir( $handle ) ) ) { + $exploded_file = explode( '.', $file ); + if ( reset( $exploded_file ) == $theme && end( $exploded_file ) == 'zip' ) { + $files[@filemtime( trailingslashit( $backup_path ) . $file )] = trailingslashit( $backup_path ) . $file; + } + } + closedir( $handle ); + krsort( $files ); + } + + if ( isset( $files ) && ! empty( $files ) ) + return array_shift( $files ); + return false; + } - $theme_backup_uri = str_replace( EWPT_BACKUP_DIR, EWPT_BACKUP_URL, $theme_backup ); + /** + * Get the backup directory URI for a given theme. + * + * @uses _get_theme_backup_dir() + * + * @access private + * @since 1.4 + * + * @param string Theme slug. + * @return bool|string Return the theme URI or false. + */ + protected function _get_theme_backup_uri( $theme ) { - if ( defined( 'EWPT_SECURE_KEY' ) ) { - $theme_backup_uri = $theme_backup_uri . '?key=' . md5( EWPT_SECURE_KEY ); + $theme_backup = $this->_get_theme_backup_dir( $theme ); + + if ( empty( $theme_backup ) ) + return false; + + $theme_backup_uri = str_replace( EWPT_BACKUP_DIR, EWPT_BACKUP_URL, $theme_backup ); + + if ( defined( 'EWPT_SECURE_KEY' ) ) { + $theme_backup_uri = $theme_backup_uri . '?key=' . md5( EWPT_SECURE_KEY ); + } + + if ( '' != $theme_backup_uri ) + return $theme_backup_uri; + + return false; } - if ( '' != $theme_backup_uri ) - return $theme_backup_uri; - - return false; - } + /** + * Force PHP to extend max_execution_time to ensure larger themes can download + * + * @author Arman Mirkazemi + * + * @access private + * @since 1.0 + * @updated 1.7.1 + */ + public function _http_request_args( $r ) { + if ( isset( $_GET['page'] ) && $_GET['page'] == EWPT_PLUGIN_SLUG && (int) ini_get( 'max_execution_time' ) < EWPT_PLUGIN_MAX_EXECUTION_TIME ) { + try { + $this->_set_max_execution_time( EWPT_PLUGIN_MAX_EXECUTION_TIME ); + } catch ( Exception $e ) { + $options = get_option( EWPT_PLUGIN_SLUG ); + $env_error = sprintf( '

    Environment error: %s Dismiss this.', $e->getMessage() ); + $env_error .= '

    '; + $options['env_errors']['max_execution_time'] = $env_error; + update_option( EWPT_PLUGIN_SLUG, $options ); + } + $r['timeout'] = EWPT_PLUGIN_MAX_EXECUTION_TIME; + } + + return $r; + } - /** - * Force PHP to extend max_execution_time to ensure larger themes can download - * - * @author Arman Mirkazemi - * - * @access private - * @since 1.0 - * @updated 1.7.1 - */ - public function _http_request_args( $r ) { - if ( isset( $_GET['page'] ) && $_GET['page'] == EWPT_PLUGIN_SLUG && (int) ini_get( 'max_execution_time' ) < EWPT_PLUGIN_MAX_EXECUTION_TIME ) { - try { - $this->_set_max_execution_time( EWPT_PLUGIN_MAX_EXECUTION_TIME ); - } catch ( Exception $e ) { - $options = get_option( EWPT_PLUGIN_SLUG ); - $env_error = sprintf( '

    Environment error: %s Dismiss this.', $e->getMessage() ); - $env_error .= '

    '; - $options['env_errors']['max_execution_time'] = $env_error; - update_option( EWPT_PLUGIN_SLUG, $options ); + /** + * Attempt to force increase to max_execution_time, throw exception with user-friendly message otherwise + * + * @author Japheth Thomson + * + * @access private + * @since 1.6.1 + */ + public function _set_max_execution_time() { + if ( ! @set_time_limit( EWPT_PLUGIN_MAX_EXECUTION_TIME ) ) { + throw new Exception( 'Unable to increase maximum execution time. Due to settings on your server, large themes may be unable to update automatically. Please consult your server administrator if this causes issues for you.' ); } - $r['timeout'] = EWPT_PLUGIN_MAX_EXECUTION_TIME; } - - return $r; - } - - /** - * Attempt to force increase to max_execution_time, throw exception with user-friendly message otherwise - * - * @author Japheth Thomson - * - * @access private - * @since 1.6.1 - */ - public function _set_max_execution_time() { - if ( ! @set_time_limit( EWPT_PLUGIN_MAX_EXECUTION_TIME ) ) { - throw new Exception( 'Unable to increase maximum execution time. Due to settings on your server, large themes may be unable to update automatically. Please consult your server administrator if this causes issues for you.' ); + + /** + * Ajax method for hiding dismissable admin notices. + * Forked from original code by Tom McFarlin. + * + * @author Japheth Thomson + * + * @access private + * @since 1.6.1 + */ + public function _hide_admin_notification() { + + if( wp_verify_nonce( $_REQUEST['nonce'], 'ajax-notification-nonce' ) && ! empty( $_REQUEST['notice_id'] ) ) { + + $options = get_option( EWPT_PLUGIN_SLUG ); + + // If the update to the option is successful, send 1 back to the browser; + // Otherwise, send 0. + $options['dismissed_errors'][$_REQUEST['notice_id']] = 1; + + if ( update_option( EWPT_PLUGIN_SLUG, $options ) ) { + die( '1' ); + } else { + die( '0' ); + } // end if/else + + } // end if + } + } - + /** - * Ajax method for hiding dismissable admin notices. - * Forked from original code by Tom McFarlin. + * Instantiates the Class * - * @author Japheth Thomson - * - * @access private - * @since 1.6.1 + * @since 1.0 + * @global object */ - public function _hide_admin_notification() { - - if( wp_verify_nonce( $_REQUEST['nonce'], 'ajax-notification-nonce' ) && ! empty( $_REQUEST['notice_id'] ) ) { - - $options = get_option( EWPT_PLUGIN_SLUG ); - - // If the update to the option is successful, send 1 back to the browser; - // Otherwise, send 0. - $options['dismissed_errors'][$_REQUEST['notice_id']] = 1; - - if ( update_option( EWPT_PLUGIN_SLUG, $options ) ) { - die( '1' ); - } else { - die( '0' ); - } // end if/else - - } // end if + $envato_wp_toolkit = new Envato_WP_Toolkit(); - } - } -/** - * Instantiates the Class - * - * @since 1.0 - * @global object - */ -$envato_wp_toolkit = new Envato_WP_Toolkit(); - /* End of file index.php */ /* Location: ./index.php */ \ No newline at end of file diff --git a/readme.txt b/readme.txt index 505ef7b..c48821d 100644 --- a/readme.txt +++ b/readme.txt @@ -32,6 +32,9 @@ Below is a description of the new api-key protected Envato Marketplace API metho == Changelog == += 1.7.2 = +* Added checks to stop PHP from throwing redeclare class errors. + = 1.7.1 = * Fixed: Stop Mojo Marketplace from tracking your movements and causing long or hanging page loads. * Fixed: Fix an issue that caused the timeout to be set high globally. From 4f1341b1d2d55c3b1f82c85966241d8de8896d95 Mon Sep 17 00:00:00 2001 From: Derek Herman Date: Thu, 12 Feb 2015 14:40:26 -0800 Subject: [PATCH 04/10] check for class before using it --- includes/class-envato-backup.php | 5 ++++- readme.txt | 1 + 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/includes/class-envato-backup.php b/includes/class-envato-backup.php index 815eca6..ab0e1db 100644 --- a/includes/class-envato-backup.php +++ b/includes/class-envato-backup.php @@ -308,9 +308,12 @@ public function zip_archive() { $this->errors_to_warnings( $this->archive_method ); $this->archive_method = 'ziparchive'; + if ( ! class_exists( 'ZipArchive' ) ) + return; + $zip = new ZipArchive(); - if ( ! class_exists( 'ZipArchive' ) || ! $zip->open( $this->archive_filepath(), ZIPARCHIVE::CREATE ) ) + if ( ! $zip->open( $this->archive_filepath(), ZIPARCHIVE::CREATE ) ) return; $files_added = 0; diff --git a/readme.txt b/readme.txt index c48821d..533d31d 100644 --- a/readme.txt +++ b/readme.txt @@ -34,6 +34,7 @@ Below is a description of the new api-key protected Envato Marketplace API metho = 1.7.2 = * Added checks to stop PHP from throwing redeclare class errors. +* Fix an issue where the `ZipArchive` class was called before the `class_exists` check. = 1.7.1 = * Fixed: Stop Mojo Marketplace from tracking your movements and causing long or hanging page loads. From 882bdd910e8f8262e38556673d2119126223a288 Mon Sep 17 00:00:00 2001 From: Derek Herman Date: Thu, 12 Feb 2015 15:42:30 -0800 Subject: [PATCH 05/10] show updates on update-core.php --- includes/class-github-updater.php | 7 +++- index.php | 57 +++++++++++++++---------------- readme.txt | 1 + 3 files changed, 35 insertions(+), 30 deletions(-) diff --git a/includes/class-github-updater.php b/includes/class-github-updater.php index 3ed14e7..e50d700 100644 --- a/includes/class-github-updater.php +++ b/includes/class-github-updater.php @@ -390,8 +390,13 @@ public function api_check( $transient ) { */ public function get_plugin_info( $false, $action, $response ) { + // Include plugin updates for `list_plugin_updates()` + if ( $action == 'plugin_information' && isset( $response->slug ) && $response->slug == dirname( $this->config['slug'] ) ) { + $found_it = true; + } + // Check if this call API is for the right plugin - if ( !isset( $response->slug ) || $response->slug != $this->config['slug'] ) + if ( ! isset( $found_it ) && ( ! isset( $response->slug ) || $response->slug != $this->config['slug'] ) ) return $false; $response->slug = $this->config['slug']; diff --git a/index.php b/index.php index 2a544bd..cc3fd60 100644 --- a/index.php +++ b/index.php @@ -689,37 +689,36 @@ protected function _admin_update_check() { * @return void */ protected function _admin_init_before() { - - if ( isset( $_GET['page'] ) ) { - $page = $_GET['page']; - - /* only execute if this is the Envato WordPress Toolkit */ - if ( $page == EWPT_PLUGIN_SLUG ) { - - $this->_prepare_envato_backup(); - - /* adds thickbox for previews */ - add_thickbox(); - - /* action must be set and template or stylesheet */ - if ( isset( $_GET['action'] ) && ( isset( $_GET['template'] ) || isset( $_GET['stylesheet'] ) ) ) { - - /* get request variables */ - $action = $_GET['action']; - $template = isset( $_GET['template'] ) ? $_GET['template'] : ''; - $stylesheet = isset( $_GET['stylesheet'] ) ? $_GET['stylesheet'] : ''; - - /* required to use the switch_theme() & delete_theme() functions */ - include_once( ABSPATH . 'wp-admin/includes/theme.php' ); - - if ( 'activate' == $action ) { - $this->_activate_theme( $template, $stylesheet ); - } else if ( 'delete' == $action ) { - $this->_delete_theme( $template ); - } + + /* only execute if this is the Envato WordPress Toolkit */ + if ( isset( $_GET['page'] ) && $_GET['page'] == EWPT_PLUGIN_SLUG ) { + + $this->_prepare_envato_backup(); + + /* adds thickbox for previews */ + add_thickbox(); + + /* action must be set and template or stylesheet */ + if ( isset( $_GET['action'] ) && ( isset( $_GET['template'] ) || isset( $_GET['stylesheet'] ) ) ) { + + /* get request variables */ + $action = $_GET['action']; + $template = isset( $_GET['template'] ) ? $_GET['template'] : ''; + $stylesheet = isset( $_GET['stylesheet'] ) ? $_GET['stylesheet'] : ''; + + /* required to use the switch_theme() & delete_theme() functions */ + include_once( ABSPATH . 'wp-admin/includes/theme.php' ); + + if ( 'activate' == $action ) { + $this->_activate_theme( $template, $stylesheet ); + } else if ( 'delete' == $action ) { + $this->_delete_theme( $template ); } + } - } + + } + } /** diff --git a/readme.txt b/readme.txt index 533d31d..34f3379 100644 --- a/readme.txt +++ b/readme.txt @@ -35,6 +35,7 @@ Below is a description of the new api-key protected Envato Marketplace API metho = 1.7.2 = * Added checks to stop PHP from throwing redeclare class errors. * Fix an issue where the `ZipArchive` class was called before the `class_exists` check. +* Fixed Github Updater class so it now shows updates on `update-core.php`. = 1.7.1 = * Fixed: Stop Mojo Marketplace from tracking your movements and causing long or hanging page loads. From 3a0eaf847ab04a31bc744f34f94a87759e2edef5 Mon Sep 17 00:00:00 2001 From: Derek Herman Date: Thu, 12 Feb 2015 16:38:17 -0800 Subject: [PATCH 06/10] prep 1.7.2 i18n --- languages/envato-wordpress-toolkit.po | 170 +++++++++++++------------- 1 file changed, 85 insertions(+), 85 deletions(-) diff --git a/languages/envato-wordpress-toolkit.po b/languages/envato-wordpress-toolkit.po index 9bd7b47..aee652e 100644 --- a/languages/envato-wordpress-toolkit.po +++ b/languages/envato-wordpress-toolkit.po @@ -1,15 +1,15 @@ msgid "" msgstr "" "Project-Id-Version: Envato WordPress Toolkit\n" -"POT-Creation-Date: 2014-11-21 13:58-0800\n" -"PO-Revision-Date: 2014-11-21 13:58-0800\n" +"POT-Creation-Date: 2015-02-12 16:37-0800\n" +"PO-Revision-Date: 2015-02-12 16:37-0800\n" "Last-Translator: Derek Herman \n" "Language-Team: Envato\n" -"Language: English\n" +"Language: en\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Generator: Poedit 1.5.7\n" +"X-Generator: Poedit 1.7.4\n" "X-Poedit-KeywordsList: __;_e;__ngettext:1,2;_n:1,2;__ngettext_noop:1,2;" "_n_noop:1,2;_c;_nc:4c,1,2;_x:1,2c;_nx:4c,1,2;_nx_noop:4c,1,2;_ex:1,2c;" "esc_attr__;esc_attr_e;esc_attr_x:1,2c;esc_html__;esc_html_e;esc_html_x:1,2c\n" @@ -17,83 +17,120 @@ msgstr "" "Plural-Forms: nplurals=2; plural=n != 1;\n" "X-Poedit-SearchPath-0: ..\n" -#: ../index.php:68 +#: ../includes/class-envato-api.php:69 ../includes/class-envato-api.php:106 +#: ../includes/class-envato-api.php:160 +msgid "Please enter your Envato Marketplace Username." +msgstr "" + +#: ../includes/class-envato-api.php:73 +msgid "Please enter your Envato Marketplace API Key." +msgstr "" + +#: ../includes/class-envato-api.php:98 +msgid "The API \"set\" is a required parameter." +msgstr "" + +#: ../includes/class-envato-api.php:187 +msgid "The Envato Marketplace \"item ID\" is a required parameter." +msgstr "" + +#: ../includes/class-envato-backup.php:426 +msgid "The backup file was not created" +msgstr "" + +#: ../includes/class-envato-backup.php:495 +msgid "The following files are unreadable and could not be backed up: " +msgstr "" + +#: ../includes/class-wp-upgrader.php:22 +msgid "Downloading upgrade package from the Envato API…" +msgstr "" + +#: ../includes/class-wp-upgrader.php:26 +msgid "Backing up & removing the old version of the theme…" +msgstr "" + +#: ../includes/class-wp-upgrader.php:32 +msgid "Downloading install package from the Envato API…" +msgstr "" + +#: ../index.php:70 msgid "Envato WordPress Toolkit" msgstr "" -#: ../index.php:228 +#: ../index.php:234 msgid "Envato Toolkit" msgstr "" -#: ../index.php:329 +#: ../index.php:335 msgid "You do not have sufficient permissions to access this page." msgstr "" -#: ../index.php:361 +#: ../index.php:367 msgid "User Settings Updated." msgstr "" -#: ../index.php:362 +#: ../index.php:368 msgid "Theme Activated." msgstr "" -#: ../index.php:363 +#: ../index.php:369 msgid "Theme Deleted." msgstr "" -#: ../index.php:439 +#: ../index.php:445 #, php-format msgid "" "You're about to delete the '%s' theme. 'Cancel' to stop, 'OK' to update." msgstr "" -#: ../index.php:442 +#: ../index.php:448 msgid "" "Updating this theme will lose any customizations you have made. 'Cancel' to " "stop, 'OK' to update." msgstr "" -#: ../index.php:458 +#: ../index.php:464 #, php-format msgid "Activate “%s”" msgstr "" -#: ../index.php:458 +#: ../index.php:464 msgid "Activate" msgstr "" -#: ../index.php:460 ../index.php:462 +#: ../index.php:466 ../index.php:468 #, php-format msgid "Preview “%s”" msgstr "" -#: ../index.php:460 ../index.php:462 +#: ../index.php:466 ../index.php:468 msgid "Preview" msgstr "" -#: ../index.php:464 +#: ../index.php:470 #, php-format msgid "Delete “%s”" msgstr "" -#: ../index.php:464 +#: ../index.php:470 msgid "Delete" msgstr "" -#: ../index.php:466 +#: ../index.php:472 #, php-format msgid "View version %1$s details" msgstr "" -#: ../index.php:469 ../index.php:513 +#: ../index.php:475 ../index.php:519 msgid "Download Backup" msgstr "" -#: ../index.php:516 +#: ../index.php:522 msgid "Options:" msgstr "" -#: ../index.php:522 +#: ../index.php:528 #, php-format msgid "" "The template files are located in %2$s. The stylesheet files " @@ -101,23 +138,23 @@ msgid "" "%5$s. Changes made to the templates will affect both themes." msgstr "" -#: ../index.php:524 +#: ../index.php:530 #, php-format msgid "All of this theme’s files are located in %2$s." msgstr "" -#: ../index.php:530 +#: ../index.php:536 msgid "Tags: " msgstr "" -#: ../index.php:536 +#: ../index.php:542 #, php-format msgid "" "There is a new version of %1$s available. View version %3$s details." msgstr "" -#: ../index.php:538 +#: ../index.php:544 #, php-format msgid "" "There is a new version of %1$s available. update automatically." msgstr "" -#: ../index.php:542 +#: ../index.php:548 #, php-format msgid "" "%1$s has not been installed. View version %3$s details." msgstr "" -#: ../index.php:544 +#: ../index.php:550 #, php-format msgid "" "%1$s has not been installed. install automatically." msgstr "" -#: ../index.php:586 +#: ../index.php:592 msgid "

    Current Theme

    " msgstr "" -#: ../index.php:593 +#: ../index.php:599 msgid "

    Available Themes

    " msgstr "" -#: ../index.php:626 +#: ../index.php:632 msgid "Save Settings" msgstr "" -#: ../index.php:731 +#: ../index.php:736 msgid "User Account Information" msgstr "" -#: ../index.php:732 +#: ../index.php:737 msgid "Marketplace Username" msgstr "" -#: ../index.php:733 +#: ../index.php:738 msgid "Secret API Key" msgstr "" -#: ../index.php:734 +#: ../index.php:739 msgid "Backup Information" msgstr "" -#: ../index.php:735 +#: ../index.php:740 msgid "Skip Theme Backup" msgstr "" -#: ../index.php:736 +#: ../index.php:741 msgid "Github Updater" msgstr "" -#: ../index.php:737 +#: ../index.php:742 msgid "Deactivate Github Updater" msgstr "" -#: ../index.php:749 +#: ../index.php:754 msgid "" "To obtain your API Key, visit your \"My Settings\" page on any of the Envato " "Marketplaces. Once a valid connection has been made any changes to the API " @@ -191,7 +228,7 @@ msgid "" "possible the author has not made it available for auto install yet." msgstr "" -#: ../index.php:787 +#: ../index.php:792 msgid "" "This plugin will automatically save your theme as a ZIP archive before it " "does an upgrade. The directory those backups get saved to is wp-" @@ -201,7 +238,7 @@ msgid "" "you don't want to backup your theme you can check the box below." msgstr "" -#: ../index.php:813 +#: ../index.php:818 #, php-format msgid "" "This option lets you deactivate the %s class, so it does not load. If you " @@ -209,71 +246,34 @@ msgid "" "plugin will look for a new version on Github; check it and it stops looking." msgstr "" -#: ../index.php:844 +#: ../index.php:849 #, php-format msgid "Return to %s" msgstr "" -#: ../index.php:869 +#: ../index.php:874 msgid "You do not have sufficient permissions to install themes for this site." msgstr "" -#: ../index.php:881 +#: ../index.php:886 #, php-format msgid "Installing Theme: %s" msgstr "" -#: ../index.php:910 ../index.php:937 ../index.php:970 +#: ../index.php:915 ../index.php:942 ../index.php:975 msgid "You do not have sufficient permissions to update themes for this site." msgstr "" -#: ../index.php:939 +#: ../index.php:944 msgid "Update Theme" msgstr "" -#: ../index.php:973 +#: ../index.php:978 msgid "You do not have sufficient permissions to delete themes for this site." msgstr "" -#: ../index.php:1045 +#: ../index.php:1050 msgid "" "This .htaccess file ensures that other people cannot download your backup " "files." msgstr "" - -#: ../includes/class-envato-api.php:67 ../includes/class-envato-api.php:104 -#: ../includes/class-envato-api.php:158 -msgid "Please enter your Envato Marketplace Username." -msgstr "" - -#: ../includes/class-envato-api.php:71 -msgid "Please enter your Envato Marketplace API Key." -msgstr "" - -#: ../includes/class-envato-api.php:96 -msgid "The API \"set\" is a required parameter." -msgstr "" - -#: ../includes/class-envato-api.php:185 -msgid "The Envato Marketplace \"item ID\" is a required parameter." -msgstr "" - -#: ../includes/class-envato-backup.php:392 -msgid "The backup file was not created" -msgstr "" - -#: ../includes/class-envato-backup.php:461 -msgid "The following files are unreadable and could not be backed up: " -msgstr "" - -#: ../includes/class-wp-upgrader.php:22 -msgid "Downloading upgrade package from the Envato API…" -msgstr "" - -#: ../includes/class-wp-upgrader.php:26 -msgid "Backing up & removing the old version of the theme…" -msgstr "" - -#: ../includes/class-wp-upgrader.php:32 -msgid "Downloading install package from the Envato API…" -msgstr "" From f373f6393a28c4997a5299154a01ac183d6f2210 Mon Sep 17 00:00:00 2001 From: Derek Herman Date: Thu, 12 Feb 2015 19:06:14 -0800 Subject: [PATCH 07/10] optimizing the http requests --- includes/class-github-updater.php | 161 +++++++++++------------------- index.php | 20 ++-- readme.txt | 4 +- 3 files changed, 70 insertions(+), 115 deletions(-) diff --git a/includes/class-github-updater.php b/includes/class-github-updater.php index e50d700..f262900 100644 --- a/includes/class-github-updater.php +++ b/includes/class-github-updater.php @@ -1,41 +1,20 @@ - * @link http://jkudish.com - * @package WP_GitHub_Updater - * @license http://www.gnu.org/copyleft/gpl.html GNU Public License - * @copyright Copyright (c) 2011-2013, Joachim Kudish - * - * GNU General Public License, Free Software Foundation - * - * - * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * This is a derivitive work of Joachim Kudish's `WP_GitHub_Updater`. + * It has been heavily modified to work with this plugin specifically. */ class WP_GitHub_Updater { /** * GitHub Updater version */ - const VERSION = 1.6; + const VERSION = EWPT_PLUGIN_VER; /** * @var $config the config for the updater @@ -55,7 +34,6 @@ class WP_GitHub_Updater { */ private $github_data; - /** * Class Constructor * @@ -68,6 +46,7 @@ public function __construct( $config = array() ) { $defaults = array( 'slug' => plugin_basename( __FILE__ ), + 'plugin' => plugin_basename( __FILE__ ), 'proper_folder_name' => dirname( plugin_basename( __FILE__ ) ), 'sslverify' => true, 'access_token' => '', @@ -82,9 +61,7 @@ public function __construct( $config = array() ) { _doing_it_wrong( __CLASS__, $message , self::VERSION ); return; } - - $this->config['transient_base'] = substr( md5( $this->config['slug'] ), 0, 16 ); - + $this->set_defaults(); add_filter( 'pre_set_site_transient_update_plugins', array( $this, 'api_check' ) ); @@ -108,10 +85,7 @@ public function has_minimum_config() { 'api_url', 'raw_url', 'github_url', - 'zip_url', - 'requires', - 'tested', - 'readme', + 'zip_url' ); foreach ( $required_config_params as $required_param ) { @@ -140,7 +114,7 @@ public function overrule_transients() { * @return void */ public function set_defaults() { - if ( !empty( $this->config['access_token'] ) ) { + if ( ! empty( $this->config['access_token'] ) ) { // See Downloading a zipball (private repo) https://help.github.com/articles/downloading-files-from-the-command-line extract( parse_url( $this->config['zip_url'] ) ); // $scheme, $host, $path @@ -151,16 +125,28 @@ public function set_defaults() { $this->config['zip_url'] = $zip_url; } + if ( ! isset( $this->config['readme'] ) ) + $this->config['readme'] = 'readme.txt'; + + // Get the contents of the readme.txt file + $this->readme = $this->get_readme(); + if ( ! isset( $this->config['new_version'] ) ) - $this->config['new_version'] = $this->get_new_version(); + $this->config['new_version'] = $this->get_readme_header_info( 'Stable tag' ); + + if ( ! isset( $this->config['tested'] ) ) + $this->config['tested'] = $this->get_readme_header_info( 'Tested up to' ); + + if ( ! isset( $this->config['requires'] ) ) + $this->config['requires'] = $this->get_readme_header_info( 'Requires at least' ); if ( ! isset( $this->config['last_updated'] ) ) $this->config['last_updated'] = $this->get_date(); - + + $plugin_data = $this->get_plugin_data(); if ( ! isset( $this->config['description'] ) ) - $this->config['description'] = $this->get_description(); + $this->config['description'] = $plugin_data['Description']; - $plugin_data = $this->get_plugin_data(); if ( ! isset( $this->config['plugin_name'] ) ) $this->config['plugin_name'] = $plugin_data['Name']; @@ -172,13 +158,8 @@ public function set_defaults() { if ( ! isset( $this->config['homepage'] ) ) $this->config['homepage'] = $plugin_data['PluginURI']; - - if ( ! isset( $this->config['readme'] ) ) - $this->config['readme'] = 'README.md'; - } - /** * Callback fn for the http_request_timeout filter * @@ -204,58 +185,47 @@ public function http_request_sslverify( $args, $url ) { return $args; } - /** - * Get New Version from github + * Get readme.txt from github * - * @since 1.0 - * @return int $version the version number + * @since 1.7.2 + * @return int $readme The readme.txt contents */ - public function get_new_version() { - $version = get_site_transient( $this->config['transient_base'].'_new_version' ); + public function get_readme() { + $readme = get_site_transient( 'ewt_readme' ); - if ( $this->overrule_transients() || ( !isset( $version ) || !$version || '' == $version ) ) { + if ( $this->overrule_transients() || ( ! isset( $readme ) || ! $readme || '' == $readme ) ) { $raw_url = trailingslashit( $this->config['raw_url'] ) . $this->config['readme']; - $raw_url = trailingslashit( $this->config['raw_url'] ) . basename( $this->config['slug'] ); $raw_response = $this->remote_get( $raw_url ); if ( is_wp_error( $raw_response ) ) - $version = false; + return false; - if (is_array($raw_response)) { - if (!empty($raw_response['body'])) { - preg_match( '#Version\:\s*(.*)$#im', $raw_response['body'], $matches ); - } + if ( is_array( $raw_response ) && ! empty( $raw_response['body'] ) ) { + set_site_transient( 'ewt_readme', $raw_response['body'], 3600 ); } - - if ( empty( $matches[1] ) ) - $version = false; - else - $version = $matches[1]; - - // back compat for older readme version handling - $raw_response = $this->remote_get( trailingslashit( $this->config['raw_url'] ) . $this->config['readme'] ); - - if ( is_wp_error( $raw_response ) ) - return $version; - - preg_match( '#^\s*`*~Current Version\:\s*([^~]*)~#im', $raw_response['body'], $__version ); - - if ( isset( $__version[1] ) ) { - $version_readme = $__version[1]; - if ( -1 == version_compare( $version, $version_readme ) ) - $version = $version_readme; - } - - // refresh every 6 hours - if ( false !== $version ) - set_site_transient( $this->config['transient_base'].'_new_version', $version, 60*60*6 ); + } - return $version; + return $readme; } + /** + * Get readme header info + * + * @since 1.7.2 + * @return mixed + */ + public function get_readme_header_info( $search = '' ) { + if ( '' != $search && '' != $this->readme ) { + preg_match( '#' . $search . '\:\s*(.*)$#im', $this->readme, $matches ); + if ( ! empty( $matches[1] ) ) { + return $matches[1]; + } + } + return false; + } /** * Interact with GitHub @@ -276,7 +246,6 @@ public function remote_get( $query ) { return $raw_response; } - /** * Get GitHub Data from the specified repository * @@ -287,7 +256,7 @@ public function get_github_data() { if ( isset( $this->github_data ) && ! empty( $this->github_data ) ) { $github_data = $this->github_data; } else { - $github_data = get_site_transient( $this->config['transient_base'].'_github_data' ); + $github_data = get_site_transient( 'ewt_github_data' ); if ( $this->overrule_transients() || ( ! isset( $github_data ) || ! $github_data || '' == $github_data ) ) { $github_data = $this->remote_get( $this->config['api_url'] ); @@ -298,7 +267,7 @@ public function get_github_data() { $github_data = json_decode( $github_data['body'] ); // refresh every 6 hours - set_site_transient( $this->config['transient_base'].'_github_data', $github_data, 60*60*6 ); + set_site_transient( 'ewt_github_data', $github_data, 60*60*6 ); } // Store the data in this class instance for future calls @@ -308,7 +277,6 @@ public function get_github_data() { return $github_data; } - /** * Get update date * @@ -320,19 +288,6 @@ public function get_date() { return ( !empty( $_date->updated_at ) ) ? date( 'Y-m-d', strtotime( $_date->updated_at ) ) : false; } - - /** - * Get plugin description - * - * @since 1.0 - * @return string $description the description - */ - public function get_description() { - $_description = $this->get_github_data(); - return ( !empty( $_description->description ) ) ? $_description->description : false; - } - - /** * Get Plugin data * @@ -341,11 +296,10 @@ public function get_description() { */ public function get_plugin_data() { include_once ABSPATH.'/wp-admin/includes/plugin.php'; - $data = get_plugin_data( WP_PLUGIN_DIR.'/'.$this->config['slug'] ); + $data = get_plugin_data( WP_PLUGIN_DIR . '/' . $this->config['slug'] ); return $data; } - /** * Hook into the plugin update check and connect to github * @@ -367,6 +321,7 @@ public function api_check( $transient ) { $response = new stdClass; $response->new_version = $this->config['new_version']; $response->slug = $this->config['proper_folder_name']; + $response->plugin = $this->config['plugin']; $response->url = add_query_arg( array( 'access_token' => $this->config['access_token'] ), $this->config['github_url'] ); $response->package = $this->config['zip_url']; @@ -378,7 +333,6 @@ public function api_check( $transient ) { return $transient; } - /** * Get Plugin info * @@ -400,13 +354,14 @@ public function get_plugin_info( $false, $action, $response ) { return $false; $response->slug = $this->config['slug']; - $response->plugin_name = $this->config['plugin_name']; + $response->plugin = $this->config['plugin']; + $response->plugin_name = $this->config['plugin_name']; $response->version = $this->config['new_version']; $response->author = $this->config['author']; $response->homepage = $this->config['homepage']; $response->requires = $this->config['requires']; $response->tested = $this->config['tested']; - $response->downloaded = 0; + $response->downloaded = 0; $response->last_updated = $this->config['last_updated']; $response->sections = array( 'description' => $this->config['description'] ); $response->download_link = $this->config['zip_url']; diff --git a/index.php b/index.php index cc3fd60..f0fca71 100644 --- a/index.php +++ b/index.php @@ -659,17 +659,15 @@ protected function _admin_update_check() { if ( is_admin() ) { // note the use of is_admin() to double check that this is happening in the admin $config = array( - 'slug' => plugin_basename( __FILE__ ), - 'proper_folder_name' => EWPT_PLUGIN_SLUG, - 'api_url' => 'https://api.github.com/repos/envato/' . EWPT_PLUGIN_SLUG, - 'raw_url' => 'https://raw.github.com/envato/' . EWPT_PLUGIN_SLUG . '/master', - 'github_url' => 'https://github.com/envato/' . EWPT_PLUGIN_SLUG, - 'zip_url' => 'https://github.com/envato/' . EWPT_PLUGIN_SLUG . '/archive/master.zip', - 'sslverify' => true, - 'requires' => '3.6', - 'tested' => '4.1', - 'readme' => 'readme.txt', - 'access_token' => '', + 'slug' => plugin_basename( __FILE__ ), + 'plugin' => plugin_basename( __FILE__ ), + 'proper_folder_name' => EWPT_PLUGIN_SLUG, + 'api_url' => 'https://api.github.com/repos/envato/' . EWPT_PLUGIN_SLUG, + 'raw_url' => 'https://raw.githubusercontent.com/envato/' . EWPT_PLUGIN_SLUG . '/master', + 'github_url' => 'https://github.com/envato/' . EWPT_PLUGIN_SLUG, + 'zip_url' => 'https://github.com/envato/' . EWPT_PLUGIN_SLUG . '/archive/master.zip', + 'sslverify' => true, + 'access_token' => '' ); new WP_GitHub_Updater( $config ); diff --git a/readme.txt b/readme.txt index 34f3379..d03117c 100644 --- a/readme.txt +++ b/readme.txt @@ -35,7 +35,9 @@ Below is a description of the new api-key protected Envato Marketplace API metho = 1.7.2 = * Added checks to stop PHP from throwing redeclare class errors. * Fix an issue where the `ZipArchive` class was called before the `class_exists` check. -* Fixed Github Updater class so it now shows updates on `update-core.php`. +* Fixed the Github Updater class so it now shows updates on `update-core.php`. +* Changed the Github Updater class to pull in the contents of `readme.txt` to build the config array. +* Changed the `raw_url` in `_admin_update_check` to use `raw.githubusercontent`, because `raw.github` causes a second `http` request. = 1.7.1 = * Fixed: Stop Mojo Marketplace from tracking your movements and causing long or hanging page loads. From 9f1e37d128eb4d1db961da17d181f983cc64bd09 Mon Sep 17 00:00:00 2001 From: Derek Herman Date: Thu, 12 Feb 2015 19:09:08 -0800 Subject: [PATCH 08/10] make transient cache the same for both --- includes/class-github-updater.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/includes/class-github-updater.php b/includes/class-github-updater.php index f262900..ee1ff26 100644 --- a/includes/class-github-updater.php +++ b/includes/class-github-updater.php @@ -266,8 +266,8 @@ public function get_github_data() { $github_data = json_decode( $github_data['body'] ); - // refresh every 6 hours - set_site_transient( 'ewt_github_data', $github_data, 60*60*6 ); + // refresh every hour + set_site_transient( 'ewt_github_data', $github_data, 3600 ); } // Store the data in this class instance for future calls From 23d187d191cb6b25a35b9ddb902ea2ccc8de444d Mon Sep 17 00:00:00 2001 From: Derek Herman Date: Thu, 12 Feb 2015 20:58:03 -0800 Subject: [PATCH 09/10] 1.7.2 i18n --- languages/envato-wordpress-toolkit.po | 38 +++++++++++++-------------- 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/languages/envato-wordpress-toolkit.po b/languages/envato-wordpress-toolkit.po index aee652e..60bd5d1 100644 --- a/languages/envato-wordpress-toolkit.po +++ b/languages/envato-wordpress-toolkit.po @@ -1,8 +1,8 @@ msgid "" msgstr "" "Project-Id-Version: Envato WordPress Toolkit\n" -"POT-Creation-Date: 2015-02-12 16:37-0800\n" -"PO-Revision-Date: 2015-02-12 16:37-0800\n" +"POT-Creation-Date: 2015-02-12 20:57-0800\n" +"PO-Revision-Date: 2015-02-12 20:57-0800\n" "Last-Translator: Derek Herman \n" "Language-Team: Envato\n" "Language: en\n" @@ -189,35 +189,35 @@ msgstr "" msgid "Save Settings" msgstr "" -#: ../index.php:736 +#: ../index.php:734 msgid "User Account Information" msgstr "" -#: ../index.php:737 +#: ../index.php:735 msgid "Marketplace Username" msgstr "" -#: ../index.php:738 +#: ../index.php:736 msgid "Secret API Key" msgstr "" -#: ../index.php:739 +#: ../index.php:737 msgid "Backup Information" msgstr "" -#: ../index.php:740 +#: ../index.php:738 msgid "Skip Theme Backup" msgstr "" -#: ../index.php:741 +#: ../index.php:739 msgid "Github Updater" msgstr "" -#: ../index.php:742 +#: ../index.php:740 msgid "Deactivate Github Updater" msgstr "" -#: ../index.php:754 +#: ../index.php:752 msgid "" "To obtain your API Key, visit your \"My Settings\" page on any of the Envato " "Marketplaces. Once a valid connection has been made any changes to the API " @@ -228,7 +228,7 @@ msgid "" "possible the author has not made it available for auto install yet." msgstr "" -#: ../index.php:792 +#: ../index.php:790 msgid "" "This plugin will automatically save your theme as a ZIP archive before it " "does an upgrade. The directory those backups get saved to is wp-" @@ -238,7 +238,7 @@ msgid "" "you don't want to backup your theme you can check the box below." msgstr "" -#: ../index.php:818 +#: ../index.php:816 #, php-format msgid "" "This option lets you deactivate the %s class, so it does not load. If you " @@ -246,33 +246,33 @@ msgid "" "plugin will look for a new version on Github; check it and it stops looking." msgstr "" -#: ../index.php:849 +#: ../index.php:847 #, php-format msgid "Return to %s" msgstr "" -#: ../index.php:874 +#: ../index.php:872 msgid "You do not have sufficient permissions to install themes for this site." msgstr "" -#: ../index.php:886 +#: ../index.php:884 #, php-format msgid "Installing Theme: %s" msgstr "" -#: ../index.php:915 ../index.php:942 ../index.php:975 +#: ../index.php:913 ../index.php:940 ../index.php:973 msgid "You do not have sufficient permissions to update themes for this site." msgstr "" -#: ../index.php:944 +#: ../index.php:942 msgid "Update Theme" msgstr "" -#: ../index.php:978 +#: ../index.php:976 msgid "You do not have sufficient permissions to delete themes for this site." msgstr "" -#: ../index.php:1050 +#: ../index.php:1048 msgid "" "This .htaccess file ensures that other people cannot download your backup " "files." From 897ceb64399987feab2f98f9dca5c39a35c40f49 Mon Sep 17 00:00:00 2001 From: Derek Herman Date: Thu, 12 Feb 2015 21:13:05 -0800 Subject: [PATCH 10/10] fix indent --- index.php | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/index.php b/index.php index f0fca71..43fad5e 100644 --- a/index.php +++ b/index.php @@ -185,18 +185,18 @@ protected function _hooks() { } /** - * Loads the text domain. - * - * @return void - * - * @access private - * @since 1.7.1 - */ - public function _load_textdomain() { - - load_plugin_textdomain( 'envato-wordpress-toolkit', false, dirname( plugin_basename( __FILE__ ) ) . '/languages' ); - - } + * Loads the text domain. + * + * @return void + * + * @access private + * @since 1.7.1 + */ + public function _load_textdomain() { + + load_plugin_textdomain( 'envato-wordpress-toolkit', false, dirname( plugin_basename( __FILE__ ) ) . '/languages' ); + + } /** * Create a nonce for AJAX notifications