├── README.md ├── composer.json ├── icon.png ├── plugin.php └── updater.php /README.md: -------------------------------------------------------------------------------- 1 | # WordPress GitHub Plugin Updater 2 | 3 | This class is meant to be used with your GitHub hosted WordPress plugins. The purpose of the class is to allow your WordPress plugin to be updated whenever you push out a new version of your plugin, similar to the experience users know and love with the WordPress.org plugin repository. 4 | 5 | Not all plugins can or should be hosted on the WordPress.org plugin repository, or you may chose to host it on GitHub only. 6 | 7 | This class was originally developed by [Joachim Kudish](https://github.com/jkudish), but because he hasn't had a chance to update it in a while, we stepped in. We are using this class in a couple of our own plugins (dogfooding!) and will continue to develop it as we go. 8 | 9 | ## Usage instructions 10 | * The class should be included somewhere in your plugin. You will need to require the file (example: `include_once('updater.php');`). 11 | * You will need to initialize the class using something similar to this: 12 | 13 | ``` 14 | if (is_admin()) { // note the use of is_admin() to double check that this is happening in the admin 15 | $config = array( 16 | 'slug' => plugin_basename(__FILE__), // this is the slug of your plugin 17 | 'proper_folder_name' => 'plugin-name', // this is the name of the folder your plugin lives in 18 | 'api_url' => 'https://api.github.com/repos/username/repository-name', // the GitHub API url of your GitHub repo 19 | 'raw_url' => 'https://raw.github.com/username/repository-name/master', // the GitHub raw url of your GitHub repo 20 | 'github_url' => 'https://github.com/username/repository-name', // the GitHub url of your GitHub repo 21 | 'zip_url' => 'https://github.com/username/repository-name/zipball/master', // the zip url of the GitHub repo 22 | 'sslverify' => true, // whether WP should check the validity of the SSL cert when getting an update, see https://github.com/jkudish/WordPress-GitHub-Plugin-Updater/issues/2 and https://github.com/jkudish/WordPress-GitHub-Plugin-Updater/issues/4 for details 23 | 'requires' => '3.0', // which version of WordPress does your plugin require? 24 | 'tested' => '3.3', // which version of WordPress is your plugin tested up to? 25 | 'readme' => 'README.md', // which file to use as the readme for the version number 26 | 'access_token' => '', // Access private repositories by authorizing under Plugins > GitHub Updates when this example plugin is installed 27 | ); 28 | new WP_GitHub_Updater($config); 29 | } 30 | ``` 31 | 32 | * In your GitHub repository, you will need to include the following line (formatted exactly like this) anywhere in your Readme file: 33 | 34 | `~Current Version:1.4~` 35 | 36 | * You will need to update the version number anytime you update the plugin, this will ultimately let the plugin know that a new version is available. 37 | 38 | * From v1.6, the updater can pick up the version from the plugin header as well. 39 | 40 | * Support for private repository was added in v1.5 41 | 42 | ## Changelog 43 | 44 | ### 1.6 (in development) 45 | * Get version from plugin header instead of readme with backwards compatibility support for readme, added by [@ninnypants](https://github.com/ninnypants) 46 | * Better ways to handle GitHub API calls and the way the data is stored, thanks to [@coenjacobs](https://github.com/coenjacobs) 47 | * Follow WordPress code standards and remove trailing whitespace 48 | * Fix a PHP notice in the Plugins admin screen, props [@ninnypants](https://github.com/ninnypants) 49 | * Use a central function for building the query used to communicate with the GitHub API, props [@davidmosterd](https://github.com/davidmosterd) 50 | 51 | 52 | ### 1.5 53 | * Support for private repositories added by [@pdclark](http://profiles.wordpress.org/pdclark) 54 | * Additional sslverify fix 55 | 56 | ### 1.4 57 | * Minor fixes from [@sc0ttkclark](https://github.com/sc0ttkclark)'s use in Pods Framework 58 | * Added readme file into config 59 | 60 | ### 1.3 61 | * Fixed all php notices 62 | * Fixed minor bugs 63 | * Added an example plugin that's used as a test 64 | * Minor documentation/readme adjustments 65 | 66 | ### 1.2 67 | * Added phpDoc and minor syntax/readability adjusments, props [@franz-josef-kaiser](https://github.com/franz-josef-kaiser), [@GaryJones](https://github.com/GaryJones) 68 | * Added a die to prevent direct access, props [@franz-josef-kaiser](https://github.com/franz-josef-kaiser) 69 | 70 | ### 1.0.3 71 | * Fixed sslverify issue, props [@pmichael](https://github.com/pmichael) 72 | 73 | ### 1.0.2 74 | * Fixed potential timeout 75 | 76 | ### 1.0.1 77 | * Fixed potential fatal error with wp_error 78 | 79 | ### 1.0 80 | * Initial Public Release 81 | 82 | ## Credits 83 | This class was originally built by [Joachim Kudish](http://jkudish.com "Joachim Kudish") and is now being maintained by [Radish Concepts](http://www.radishconcepts.com/). 84 | 85 | ## License 86 | 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. 87 | 88 | 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. 89 | 90 | You should have received a copy of the GNU General Public License along with this program; if not, write to: 91 | 92 | Free Software Foundation, Inc. 93 | 51 Franklin Street, Fifth Floor, 94 | Boston, MA 95 | 02110-1301, USA. 96 | -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "radishconcepts/wordpress-github-plugin-updater", 3 | "description": "This class is meant to be used with your Github hosted WordPress plugins. The purpose of the class is to allow your WordPress plugin to be updated whenever you push out a new version of your plugin; similarly to the experience users know and love with the WordPress.org plugin repository.", 4 | "authors": [], 5 | "type": "library", 6 | "license": "GPL-2.0-or-later", 7 | "homepage": "https://github.com/radishconcepts/WordPress-GitHub-Plugin-Updater", 8 | "readme": "https://github.com/radishconcepts/WordPress-GitHub-Plugin-Updater/blob/master/README.md", 9 | "support": { 10 | "issues": "https://github.com/radishconcepts/WordPress-GitHub-Plugin-Updater/issues" 11 | }, 12 | "prefer-stable": true 13 | } 14 | -------------------------------------------------------------------------------- /icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/radishconcepts/WordPress-GitHub-Plugin-Updater/43d2ec0fb5830ac60054519522897b3f8b0fb646/icon.png -------------------------------------------------------------------------------- /plugin.php: -------------------------------------------------------------------------------- 1 | plugin_basename( __FILE__ ), 49 | 'proper_folder_name' => 'github-updater', 50 | 'api_url' => 'https://api.github.com/repos/jkudish/WordPress-GitHub-Plugin-Updater', 51 | 'raw_url' => 'https://raw.github.com/jkudish/WordPress-GitHub-Plugin-Updater/master', 52 | 'github_url' => 'https://github.com/jkudish/WordPress-GitHub-Plugin-Updater', 53 | 'zip_url' => 'https://github.com/jkudish/WordPress-GitHub-Plugin-Updater/archive/master.zip', 54 | 'sslverify' => true, 55 | 'requires' => '3.0', 56 | 'tested' => '3.3', 57 | 'readme' => 'README.md', 58 | 'access_token' => '', 59 | ); 60 | 61 | new WP_GitHub_Updater( $config ); 62 | 63 | } 64 | 65 | } 66 | 67 | 68 | 69 | 70 | /** 71 | * Configuration assistant for updating from private repositories. 72 | * Do not include this in your plugin once you get your access token. 73 | * 74 | * @see /wp-admin/plugins.php?page=github-updater 75 | */ 76 | class WPGitHubUpdaterSetup { 77 | 78 | /** 79 | * Full file system path to the main plugin file 80 | * 81 | * @var string 82 | */ 83 | var $plugin_file; 84 | 85 | /** 86 | * Path to the main plugin file relative to WP_CONTENT_DIR/plugins 87 | * 88 | * @var string 89 | */ 90 | var $plugin_basename; 91 | 92 | /** 93 | * Name of options page hook 94 | * 95 | * @var string 96 | */ 97 | var $options_page_hookname; 98 | 99 | function __construct() { 100 | 101 | // Full path and plugin basename of the main plugin file 102 | $this->plugin_file = __FILE__; 103 | $this->plugin_basename = plugin_basename( $this->plugin_file ); 104 | 105 | add_action( 'admin_init', array( $this, 'settings_fields' ) ); 106 | add_action( 'admin_menu', array( $this, 'add_page' ) ); 107 | add_action( 'network_admin_menu', array( $this, 'add_page' ) ); 108 | 109 | add_action( 'wp_ajax_set_github_oauth_key', array( $this, 'ajax_set_github_oauth_key' ) ); 110 | } 111 | 112 | /** 113 | * Add the options page 114 | * 115 | * @return none 116 | */ 117 | function add_page() { 118 | if ( current_user_can ( 'manage_options' ) ) { 119 | $this->options_page_hookname = add_plugins_page ( __( 'GitHub Updates', 'github_plugin_updater' ), __( 'GitHub Updates', 'github_plugin_updater' ), 'manage_options', 'github-updater', array( $this, 'admin_page' ) ); 120 | add_filter( "network_admin_plugin_action_links_{$this->plugin_basename}", array( $this, 'filter_plugin_actions' ) ); 121 | add_filter( "plugin_action_links_{$this->plugin_basename}", array( $this, 'filter_plugin_actions' ) ); 122 | } 123 | } 124 | 125 | /** 126 | * Add fields and groups to the settings page 127 | * 128 | * @return none 129 | */ 130 | public function settings_fields() { 131 | register_setting( 'ghupdate', 'ghupdate', array( $this, 'settings_validate' ) ); 132 | 133 | // Sections: ID, Label, Description callback, Page ID 134 | add_settings_section( 'ghupdate_private', 'Private Repositories', array( $this, 'private_description' ), 'github-updater' ); 135 | 136 | // Private Repo Fields: ID, Label, Display callback, Menu page slug, Form section, callback arguements 137 | add_settings_field( 138 | 'client_id', 'Client ID', array( $this, 'input_field' ), 'github-updater', 'ghupdate_private', 139 | array( 140 | 'id' => 'client_id', 141 | 'type' => 'text', 142 | 'description' => '', 143 | ) 144 | ); 145 | add_settings_field( 146 | 'client_secret', 'Client Secret', array( $this, 'input_field' ), 'github-updater', 'ghupdate_private', 147 | array( 148 | 'id' => 'client_secret', 149 | 'type' => 'text', 150 | 'description' => '', 151 | ) 152 | ); 153 | add_settings_field( 154 | 'access_token', 'Access Token', array( $this, 'token_field' ), 'github-updater', 'ghupdate_private', 155 | array( 156 | 'id' => 'access_token', 157 | ) 158 | ); 159 | add_settings_field( 160 | 'gh_authorize', '

', null, 'github-updater', 'ghupdate_private', null 161 | ); 162 | 163 | } 164 | 165 | public function private_description() { 166 | ?> 167 |

Updating from private repositories requires a one-time application setup and authorization. These steps will not need to be repeated for other sites once you receive your access token.

168 |

Follow these steps:

169 |
    170 |
  1. Create an application with the Main URL and Callback URL both set to
  2. 171 |
  3. Copy the Client ID and Client Secret from your application details into the fields below.
  4. 172 |
  5. Authorize with GitHub.
  6. 173 |
174 | 182 | 183 | 184 | 194 |

Input Client ID and Client Secret, then Authorize with GitHub.

195 | 196 | 199 | 200 |

Add to the $config array: 'access_token' => '', 201 | 204 | ' . __( 'Setup', 'github_plugin_updater' ) . ''; 239 | array_unshift( $links, $settings_link ); 240 | return $links; 241 | } 242 | 243 | /** 244 | * Output the setup page 245 | * 246 | * @return none 247 | */ 248 | function admin_page() { 249 | $this->maybe_authorize(); 250 | ?> 251 |

252 | 253 |
254 | 255 |

256 |
257 | 258 |
259 |
260 | 265 |
266 |
267 | 268 |
269 | 'repo', 285 | 'client_id' => $gh['client_id'], 286 | 'redirect_uri' => $redirect_uri, 287 | ); 288 | $query = add_query_arg( $query_args, $query ); 289 | wp_redirect( $query ); 290 | 291 | exit; 292 | 293 | } 294 | 295 | public function ajax_set_github_oauth_key() { 296 | $gh = get_option( 'ghupdate' ); 297 | 298 | $query = admin_url( 'plugins.php' ); 299 | $query = add_query_arg( array( 'page' => 'github-updater' ), $query ); 300 | 301 | if ( isset( $_GET['code'] ) ) { 302 | // Receive authorized token 303 | $query = 'https://github.com/login/oauth/access_token'; 304 | $query_args = array( 305 | 'client_id' => $gh['client_id'], 306 | 'client_secret' => $gh['client_secret'], 307 | 'code' => $_GET['code'], 308 | ); 309 | $query = add_query_arg( $query_args, $query ); 310 | $response = wp_remote_get( $query, array( 'sslverify' => false ) ); 311 | parse_str( $response['body'] ); // populates $access_token, $token_type 312 | 313 | if ( !empty( $access_token ) ) { 314 | $gh['access_token'] = $access_token; 315 | update_option( 'ghupdate', $gh ); 316 | } 317 | 318 | wp_redirect( admin_url( 'plugins.php?page=github-updater' ) ); 319 | exit; 320 | 321 | }else { 322 | $query = add_query_arg( array( 'authorize'=>'false' ), $query ); 323 | wp_redirect( $query ); 324 | exit; 325 | } 326 | } 327 | } 328 | add_action( 'init', create_function( '', 'global $WPGitHubUpdaterSetup; $WPGitHubUpdaterSetup = new WPGitHubUpdaterSetup();' ) ); -------------------------------------------------------------------------------- /updater.php: -------------------------------------------------------------------------------- 1 | 12 | * @link http://jkudish.com 13 | * @package WP_GitHub_Updater 14 | * @license http://www.gnu.org/copyleft/gpl.html GNU Public License 15 | * @copyright Copyright (c) 2011-2013, Joachim Kudish 16 | * 17 | * GNU General Public License, Free Software Foundation 18 | * 19 | * 20 | * This program is free software; you can redistribute it and/or modify 21 | * it under the terms of the GNU General Public License as published by 22 | * the Free Software Foundation; either version 2 of the License, or 23 | * (at your option) any later version. 24 | * 25 | * This program is distributed in the hope that it will be useful, 26 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 27 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 28 | * GNU General Public License for more details. 29 | * 30 | * You should have received a copy of the GNU General Public License 31 | * along with this program; if not, write to the Free Software 32 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 33 | */ 34 | class WP_GitHub_Updater { 35 | 36 | /** 37 | * GitHub Updater version 38 | */ 39 | const VERSION = 1.6; 40 | 41 | /** 42 | * @var $config the config for the updater 43 | * @access public 44 | */ 45 | var $config; 46 | 47 | /** 48 | * @var $missing_config any config that is missing from the initialization of this instance 49 | * @access public 50 | */ 51 | var $missing_config; 52 | 53 | /** 54 | * @var $github_data temporiraly store the data fetched from GitHub, allows us to only load the data once per class instance 55 | * @access private 56 | */ 57 | private $github_data; 58 | 59 | 60 | /** 61 | * Class Constructor 62 | * 63 | * @since 1.0 64 | * @param array $config the configuration required for the updater to work 65 | * @see has_minimum_config() 66 | * @return void 67 | */ 68 | public function __construct( $config = array() ) { 69 | 70 | $defaults = array( 71 | 'slug' => plugin_basename( __FILE__ ), 72 | 'proper_folder_name' => dirname( plugin_basename( __FILE__ ) ), 73 | 'sslverify' => true, 74 | 'access_token' => '', 75 | ); 76 | 77 | $this->config = wp_parse_args( $config, $defaults ); 78 | 79 | // if the minimum config isn't set, issue a warning and bail 80 | if ( ! $this->has_minimum_config() ) { 81 | $message = 'The GitHub Updater was initialized without the minimum required configuration, please check the config in your plugin. The following params are missing: '; 82 | $message .= implode( ',', $this->missing_config ); 83 | _doing_it_wrong( __CLASS__, $message , self::VERSION ); 84 | return; 85 | } 86 | 87 | $this->set_defaults(); 88 | 89 | add_filter( 'pre_set_site_transient_update_plugins', array( $this, 'api_check' ) ); 90 | 91 | // Hook into the plugin details screen 92 | add_filter( 'plugins_api', array( $this, 'get_plugin_info' ), 10, 3 ); 93 | add_filter( 'upgrader_post_install', array( $this, 'upgrader_post_install' ), 10, 3 ); 94 | 95 | // set timeout 96 | add_filter( 'http_request_timeout', array( $this, 'http_request_timeout' ) ); 97 | 98 | // set sslverify for zip download 99 | add_filter( 'http_request_args', array( $this, 'http_request_sslverify' ), 10, 2 ); 100 | } 101 | 102 | public function has_minimum_config() { 103 | 104 | $this->missing_config = array(); 105 | 106 | $required_config_params = array( 107 | 'api_url', 108 | 'raw_url', 109 | 'github_url', 110 | 'zip_url', 111 | 'requires', 112 | 'tested', 113 | 'readme', 114 | ); 115 | 116 | foreach ( $required_config_params as $required_param ) { 117 | if ( empty( $this->config[$required_param] ) ) 118 | $this->missing_config[] = $required_param; 119 | } 120 | 121 | return ( empty( $this->missing_config ) ); 122 | } 123 | 124 | 125 | /** 126 | * Check wether or not the transients need to be overruled and API needs to be called for every single page load 127 | * 128 | * @return bool overrule or not 129 | */ 130 | public function overrule_transients() { 131 | return ( defined( 'WP_GITHUB_FORCE_UPDATE' ) && WP_GITHUB_FORCE_UPDATE ); 132 | } 133 | 134 | 135 | /** 136 | * Set defaults 137 | * 138 | * @since 1.2 139 | * @return void 140 | */ 141 | public function set_defaults() { 142 | if ( !empty( $this->config['access_token'] ) ) { 143 | 144 | // See Downloading a zipball (private repo) https://help.github.com/articles/downloading-files-from-the-command-line 145 | extract( parse_url( $this->config['zip_url'] ) ); // $scheme, $host, $path 146 | 147 | $zip_url = $scheme . '://api.github.com/repos' . $path; 148 | $zip_url = add_query_arg( array( 'access_token' => $this->config['access_token'] ), $zip_url ); 149 | 150 | $this->config['zip_url'] = $zip_url; 151 | } 152 | 153 | 154 | if ( ! isset( $this->config['new_version'] ) ) 155 | $this->config['new_version'] = $this->get_new_version(); 156 | 157 | if ( ! isset( $this->config['last_updated'] ) ) 158 | $this->config['last_updated'] = $this->get_date(); 159 | 160 | if ( ! isset( $this->config['description'] ) ) 161 | $this->config['description'] = $this->get_description(); 162 | 163 | $plugin_data = $this->get_plugin_data(); 164 | if ( ! isset( $this->config['plugin_name'] ) ) 165 | $this->config['plugin_name'] = $plugin_data['Name']; 166 | 167 | if ( ! isset( $this->config['version'] ) ) 168 | $this->config['version'] = $plugin_data['Version']; 169 | 170 | if ( ! isset( $this->config['author'] ) ) 171 | $this->config['author'] = $plugin_data['Author']; 172 | 173 | if ( ! isset( $this->config['homepage'] ) ) 174 | $this->config['homepage'] = $plugin_data['PluginURI']; 175 | 176 | if ( ! isset( $this->config['readme'] ) ) 177 | $this->config['readme'] = 'README.md'; 178 | 179 | } 180 | 181 | 182 | /** 183 | * Callback fn for the http_request_timeout filter 184 | * 185 | * @since 1.0 186 | * @return int timeout value 187 | */ 188 | public function http_request_timeout() { 189 | return 2; 190 | } 191 | 192 | /** 193 | * Callback fn for the http_request_args filter 194 | * 195 | * @param unknown $args 196 | * @param unknown $url 197 | * 198 | * @return mixed 199 | */ 200 | public function http_request_sslverify( $args, $url ) { 201 | if ( $this->config[ 'zip_url' ] == $url ) 202 | $args[ 'sslverify' ] = $this->config[ 'sslverify' ]; 203 | 204 | return $args; 205 | } 206 | 207 | 208 | /** 209 | * Get New Version from GitHub 210 | * 211 | * @since 1.0 212 | * @return int $version the version number 213 | */ 214 | public function get_new_version() { 215 | $version = get_site_transient( md5($this->config['slug']).'_new_version' ); 216 | 217 | if ( $this->overrule_transients() || ( !isset( $version ) || !$version || '' == $version ) ) { 218 | 219 | $raw_response = $this->remote_get( trailingslashit( $this->config['raw_url'] ) . basename( $this->config['slug'] ) ); 220 | 221 | if ( is_wp_error( $raw_response ) ) 222 | $version = false; 223 | 224 | if (is_array($raw_response)) { 225 | if (!empty($raw_response['body'])) 226 | preg_match( '/.*Version\:\s*(.*)$/mi', $raw_response['body'], $matches ); 227 | } 228 | 229 | if ( empty( $matches[1] ) ) 230 | $version = false; 231 | else 232 | $version = $matches[1]; 233 | 234 | // back compat for older readme version handling 235 | // only done when there is no version found in file name 236 | if ( false === $version ) { 237 | $raw_response = $this->remote_get( trailingslashit( $this->config['raw_url'] ) . $this->config['readme'] ); 238 | 239 | if ( is_wp_error( $raw_response ) ) 240 | return $version; 241 | 242 | preg_match( '#^\s*`*~Current Version\:\s*([^~]*)~#im', $raw_response['body'], $__version ); 243 | 244 | if ( isset( $__version[1] ) ) { 245 | $version_readme = $__version[1]; 246 | if ( -1 == version_compare( $version, $version_readme ) ) 247 | $version = $version_readme; 248 | } 249 | } 250 | 251 | // refresh every 6 hours 252 | if ( false !== $version ) 253 | set_site_transient( md5($this->config['slug']).'_new_version', $version, 60*60*6 ); 254 | } 255 | 256 | return $version; 257 | } 258 | 259 | 260 | /** 261 | * Interact with GitHub 262 | * 263 | * @param string $query 264 | * 265 | * @since 1.6 266 | * @return mixed 267 | */ 268 | public function remote_get( $query ) { 269 | if ( ! empty( $this->config['access_token'] ) ) 270 | $query = add_query_arg( array( 'access_token' => $this->config['access_token'] ), $query ); 271 | 272 | $raw_response = wp_remote_get( $query, array( 273 | 'sslverify' => $this->config['sslverify'] 274 | ) ); 275 | 276 | return $raw_response; 277 | } 278 | 279 | 280 | /** 281 | * Get GitHub Data from the specified repository 282 | * 283 | * @since 1.0 284 | * @return array $github_data the data 285 | */ 286 | public function get_github_data() { 287 | if ( isset( $this->github_data ) && ! empty( $this->github_data ) ) { 288 | $github_data = $this->github_data; 289 | } else { 290 | $github_data = get_site_transient( md5($this->config['slug']).'_github_data' ); 291 | 292 | if ( $this->overrule_transients() || ( ! isset( $github_data ) || ! $github_data || '' == $github_data ) ) { 293 | $github_data = $this->remote_get( $this->config['api_url'] ); 294 | 295 | if ( is_wp_error( $github_data ) ) 296 | return false; 297 | 298 | $github_data = json_decode( $github_data['body'] ); 299 | 300 | // refresh every 6 hours 301 | set_site_transient( md5($this->config['slug']).'_github_data', $github_data, 60*60*6 ); 302 | } 303 | 304 | // Store the data in this class instance for future calls 305 | $this->github_data = $github_data; 306 | } 307 | 308 | return $github_data; 309 | } 310 | 311 | 312 | /** 313 | * Get update date 314 | * 315 | * @since 1.0 316 | * @return string $date the date 317 | */ 318 | public function get_date() { 319 | $_date = $this->get_github_data(); 320 | return ( !empty( $_date->updated_at ) ) ? date( 'Y-m-d', strtotime( $_date->updated_at ) ) : false; 321 | } 322 | 323 | 324 | /** 325 | * Get plugin description 326 | * 327 | * @since 1.0 328 | * @return string $description the description 329 | */ 330 | public function get_description() { 331 | $_description = $this->get_github_data(); 332 | return ( !empty( $_description->description ) ) ? $_description->description : false; 333 | } 334 | 335 | 336 | /** 337 | * Get Plugin data 338 | * 339 | * @since 1.0 340 | * @return object $data the data 341 | */ 342 | public function get_plugin_data() { 343 | include_once ABSPATH.'/wp-admin/includes/plugin.php'; 344 | $data = get_plugin_data( WP_PLUGIN_DIR.'/'.$this->config['slug'] ); 345 | return $data; 346 | } 347 | 348 | 349 | /** 350 | * Hook into the plugin update check and connect to GitHub 351 | * 352 | * @since 1.0 353 | * @param object $transient the plugin data transient 354 | * @return object $transient updated plugin data transient 355 | */ 356 | public function api_check( $transient ) { 357 | 358 | // Check if the transient contains the 'checked' information 359 | // If not, just return its value without hacking it 360 | if ( empty( $transient->checked ) ) 361 | return $transient; 362 | 363 | // check the version and decide if it's new 364 | $update = version_compare( $this->config['new_version'], $this->config['version'] ); 365 | 366 | if ( 1 === $update ) { 367 | $response = new stdClass; 368 | $response->new_version = $this->config['new_version']; 369 | $response->slug = $this->config['proper_folder_name']; 370 | $response->url = add_query_arg( array( 'access_token' => $this->config['access_token'] ), $this->config['github_url'] ); 371 | $response->package = $this->config['zip_url']; 372 | 373 | // If response is false, don't alter the transient 374 | if ( false !== $response ) 375 | $transient->response[ $this->config['slug'] ] = $response; 376 | } 377 | 378 | return $transient; 379 | } 380 | 381 | 382 | /** 383 | * Get Plugin info 384 | * 385 | * @since 1.0 386 | * @param bool $false always false 387 | * @param string $action the API function being performed 388 | * @param object $args plugin arguments 389 | * @return object $response the plugin info 390 | */ 391 | public function get_plugin_info( $false, $action, $response ) { 392 | 393 | // Check if this call API is for the right plugin 394 | if ( !isset( $response->slug ) || $response->slug != $this->config['slug'] ) 395 | return false; 396 | 397 | $response->slug = $this->config['slug']; 398 | $response->plugin_name = $this->config['plugin_name']; 399 | $response->version = $this->config['new_version']; 400 | $response->author = $this->config['author']; 401 | $response->homepage = $this->config['homepage']; 402 | $response->requires = $this->config['requires']; 403 | $response->tested = $this->config['tested']; 404 | $response->downloaded = 0; 405 | $response->last_updated = $this->config['last_updated']; 406 | $response->sections = array( 'description' => $this->config['description'] ); 407 | $response->download_link = $this->config['zip_url']; 408 | 409 | return $response; 410 | } 411 | 412 | 413 | /** 414 | * Upgrader/Updater 415 | * Move & activate the plugin, echo the update message 416 | * 417 | * @since 1.0 418 | * @param boolean $true always true 419 | * @param mixed $hook_extra not used 420 | * @param array $result the result of the move 421 | * @return array $result the result of the move 422 | */ 423 | public function upgrader_post_install( $true, $hook_extra, $result ) { 424 | 425 | global $wp_filesystem; 426 | 427 | // Move & Activate 428 | $proper_destination = WP_PLUGIN_DIR.'/'.$this->config['proper_folder_name']; 429 | $wp_filesystem->move( $result['destination'], $proper_destination ); 430 | $result['destination'] = $proper_destination; 431 | $activate = activate_plugin( WP_PLUGIN_DIR.'/'.$this->config['slug'] ); 432 | 433 | // Output the update message 434 | $fail = __( 'The plugin has been updated, but could not be reactivated. Please reactivate it manually.', 'github_plugin_updater' ); 435 | $success = __( 'Plugin reactivated successfully.', 'github_plugin_updater' ); 436 | echo is_wp_error( $activate ) ? $fail : $success; 437 | return $result; 438 | 439 | } 440 | } --------------------------------------------------------------------------------