diff --git a/pau-updater.php b/pau-updater.php index 4a29229..33bf51c 100644 --- a/pau-updater.php +++ b/pau-updater.php @@ -3,7 +3,7 @@ Plugin Name: Pau-Updater Plugin URI: http://www.paucapo.com Description: Plugins updater -Version: 0.1 +Version: 0.1.1 Author: Pau Capó Author URI: http://www.paucapo.com Gitea Host: https://git.paucapo.com/ @@ -21,80 +21,315 @@ TODO: defined( 'ABSPATH' ) or exit; class Pau_Updater { - public $update_data = array(); - public $active_plugins = array(); + + public $plugins = array(); + public $themes = array(); + public $remote_managemnet = true; function __construct() { - add_action( 'admin_init', array( $this, 'admin_init' ) ); - add_filter( 'plugins_api', array( $this, 'plugins_api' ), 10, 3 ); - add_filter( 'pre_set_site_transient_update_plugins', array( $this, 'set_update_data' ) ); - add_filter( 'upgrader_source_selection', array( $this, 'upgrader_source_selection' ), 10, 4 ); - add_filter( 'extra_plugin_headers', array( $this, 'extra_plugin_headers' ) ); + // normal check + add_action('admin_init', array($this, 'admin_init')); + + // force check in core update, plugins and themes pages + add_action('admin_init', array($this, 'admin_pages_update_transient')); + + // plugins checks + add_filter('plugins_api', array($this, 'plugins_api'), 10, 3); + add_filter('pre_set_site_transient_update_plugins', array($this, 'pre_set_site_transient_update_plugins')); + + // themes checks + add_filter('pre_set_site_transient_update_themes', array($this, 'pre_set_site_transient_update_themes')); + + // rename directories + add_filter('upgrader_source_selection', array($this, 'upgrader_source_selection'), 10, 4); + + // extra plugins and themes headers (Gitea Host and Gitea URI) + add_filter('extra_plugin_headers', array($this, 'extra_headers')); + add_filter('extra_theme_headers', array($this, 'extra_headers')); + + // remote management + add_action('wp_update_plugins', array($this, 'forced_meta_update_plugins')); + add_action('wp_update_themes', array($this, 'forced_meta_update_themes')); + add_action('wp_ajax_nopriv_ithemes_sync_request', array($this, 'forced_meta_update_remote_management')); + add_action('update_option_auto_updater.lock', array($this, 'forced_meta_update_remote_management')); } function admin_init() { - $now = strtotime( 'now' ); - $last_checked = (int) get_option( 'ghu_last_checked' ); - $check_interval = 0;//apply_filters( 'ghu_check_interval', ( 60 * 60 * 12 ) ); - $this->update_data = (array) get_option( 'ghu_update_data' ); - $active = (array) get_option( 'active_plugins' ); - foreach ( $active as $slug ) { - $this->active_plugins[ $slug ] = true; + // check interval data + $now = strtotime('now'); + $last_checked = (int) get_option('pu_last_checked'); + $check_interval = apply_filters('pu_check_interval', (60 * 60 * 0)); + + // cached data + $this->plugins = (array)get_option('pu_plugins'); + $this->themes = (array)get_option('pu_themes'); + + // if is time... update data + if (($now - $last_checked) > $check_interval) { + $this->plugins = $this->get_gitea_plugins(); + update_option('pu_plugins', $this->plugins); + + $this->themes = $this->get_gitea_themes(); + update_option('pu_themes', $this->plugins); + + update_option('pu_last_checked', $now); } - // transient expiration - if ( ( $now - $last_checked ) > $check_interval ) { - $this->update_data = $this->get_gitea_updates(); - - update_option( 'ghu_update_data', $this->update_data ); - update_option( 'ghu_last_checked', $now ); - } } - function get_gitea_updates() { + function get_gitea_plugins() { $plugin_data = array(); $plugins = get_plugins(); - foreach ( $plugins as $slug => $info ) { - if ( isset( $this->active_plugins[ $slug ] ) && ! empty( $info['Gitea URI'] ) && ! empty( $info['Gitea Host'] ) ) { - $temp = array( - 'plugin' => $slug, - 'slug' => trim( dirname( $slug ), '/' ), - 'file' => basename($slug), - 'name' => $info['Name'], - 'gitea_host' => $info['Gitea Host'], - 'gitea_repo' => $info['Gitea URI'], - 'description' => $info['Description'], + + foreach ($plugins as $plugin_slug => $plugin) { + + if (!empty($plugin['Gitea URI']) && !empty($plugin['Gitea Host'])) { + + // this is a gitea plugin + + $slug = trim(dirname($plugin_slug), '/'); + $host = $plugin['Gitea Host']; + $repo = $plugin['Gitea URI']; + + $url = $this->get_gitea_url($host, $repo, '/raw/master/'.basename($plugin_slug)); + if ($url == false) + break; + + $version = $this->get_gitea_version($url, 'plugin'); + if ($version == false) + break; + // here we have the remote version from gitea/repo/plugin_file + + // building the plugin data + $gitea = array( + 'plugin' => $plugin_slug, + 'slug' => $slug, + 'file' => basename($plugin_slug), + 'name' => $plugin['Name'], + 'gitea_host' => $plugin['Gitea Host'], + 'gitea_repo' => $plugin['Gitea URI'], + 'description' => $plugin['Description'], + 'url' => $host.$repo, + 'local_version' => strtolower($plugin['Version']), + 'new_version' => $version, + 'package' => $this->get_gitea_url($host, $repo, '/archive/master.zip'), ); - - // TODO - $access_token = '9ebc78834767d2ce0f95ec8a5ab597bc1fbc9ed6'; - - $url = $temp['gitea_host'].'api/v1/repos/'.$temp['gitea_repo'].'/raw/master/'.$temp['file'].'?access_token='.$access_token; - $request = wp_remote_get( $url ); - - // WP error or rate limit exceeded - if ( is_wp_error( $request ) || 200 != wp_remote_retrieve_response_code( $request ) ) { - break; - } - - $headers = $this->get_file_headers($request['body'], 'plugin'); - - $temp['new_version'] = $headers['Version']; - $temp['url'] = $temp['gitea_host'].$temp['gitea_repo']; - $temp['package'] = $temp['gitea_host'].'api/v1/repos/'.$temp['gitea_repo'].'/archive/master.zip?access_token='.$access_token; - - $plugin_data[ $slug ] = $temp; + $plugin_data[$slug] = $gitea; } } return $plugin_data; } - function get_file_headers( $contents, $type ) { + function get_gitea_themes() { + $theme_data = array(); + $themes = wp_get_themes(); + + foreach ( $themes as $theme ) { + + if ($theme->get('Gitea Host') != '' && $theme->get('Gitea URI')) { + + // this is a gitea theme + + $slug = $theme->stylesheet; + $host = $theme->get('Gitea Host'); + $repo = $theme->get('Gitea URI'); + + $url = $this->get_gitea_url($host, $repo, '/raw/master/style.css'); + if ($url == false) + break; + + $version = $this->get_gitea_version($url, 'theme'); + if ($version == false) + break; + // here we have the remote version from gitea/repo/style.css + + // building the theme data + $gitea = array( + 'slug' => $slug, + 'name' => $theme->get('Name'), + 'gitea_host' => $theme->get('Gitea Host'), + 'gitea_repo' => $theme->get('Gitea URI'), + 'description' => $theme->get('Description'), + 'author' => $theme->get('Author'), + 'url' => $theme->get('AuthorURI'),//$host.$repo, + 'local_version' => strtolower($theme->get('Version')), + 'new_version' => $version, + 'package' => $this->get_gitea_url($host, $repo, '/archive/master.zip'), + ); + + $theme_data[$slug] = $gitea; + } + + } + + return $theme_data; + } + + function get_gitea_token($host) { + return '9ebc78834767d2ce0f95ec8a5ab597bc1fbc9ed6'; + } + + function get_gitea_url($host, $repo, $args = '') { + $access_token = $this->get_gitea_token($host); + if (!$access_token) return false; + return $host.'api/v1/repos/'.$repo.$args.'?access_token='.$access_token; + } + + function get_gite_file($url) { + $request = wp_remote_get($url); + + if (is_wp_error($request) || 200 != wp_remote_retrieve_response_code($request)) { + return false; + } + + // in $request['body'] we have the content from the file + return $request; + } + + function get_gitea_version($url, $type) { + + $request = $this->get_gite_file($url); + + if (!$request) return false; + + // get the headers + $headers = $this->get_file_headers($request['body'], $type); + + return isset($headers['Version']) ? $headers['Version'] : false; + } + + function plugins_api($default = false, $action, $args) { + if ('plugin_information' != $action) + return $default; + + if (!isset($this->plugins[$args->slug])) + return $default; + + // plugin information (view notes befor update) + + $plugin = $this->plugins[$args->slug]; + + return (object) array( + 'name' => $plugin['name'], + 'slug' => $plugin['plugin'], + 'version' => $plugin['new_version'], + 'sections' => array( + 'description' => $plugin['description'] + ), + 'download_link' => $plugin['package'], + 'homepage' => $plugin['url'], + ); + + } + + function pre_set_site_transient_update_plugins($transient) { + // check if some plugin needs update using the cached data + + foreach ($this->plugins as $plugin => $git_plugin) { + + if (version_compare($git_plugin['local_version'], $git_plugin['new_version'], '<')) { + $transient->response[$git_plugin['plugin']] = (object) $git_plugin; + } + + } + + return $transient; + } + + function pre_set_site_transient_update_themes($transient) { + // check if some theme needs update + + foreach ($this->themes as $theme => $git_theme) { + + if (version_compare($git_theme['local_version'], $git_theme['new_version'], '<')) { + $transient->response[$theme] = (array)$git_theme; + } + + } + + return $transient; + } + + public function admin_pages_update_transient() { + // force update data on 'plugins.php', 'themes.php', 'update-core.php' + + global $pagenow; + + $admin_pages = array('plugins.php', 'themes.php', 'update-core.php'); + $is_admin_page = in_array($pagenow, $admin_pages) ? true : false; + $transient = 'update_'.rtrim($pagenow, '.php'); + $transient = 'update_update-core' === $transient ? 'update_core' : $transient; + + if ($is_admin_page) { + $this->make_update_transient_current($transient); + } + + remove_filter('admin_init', array($this, 'admin_pages_update_transient')); + } + + function make_update_transient_current($transient) { + if (!in_array($transient, array('update_plugins', 'update_themes', 'update_core'))) { + return; + } + + if (current_user_can($transient)) { + $current = get_site_transient($transient); + switch ($transient) { + case 'update_plugins': + $this->forced_meta_update_plugins(true); + $current = $this->pre_set_site_transient_update_plugins($current); + break; + case 'update_themes': + $this->forced_meta_update_themes(true); + $current = $this->pre_set_site_transient_update_themes($current); + break; + case 'update_core': + $this->forced_meta_update_plugins(true); + $current = $this->pre_set_site_transient_update_plugins($current); + $this->forced_meta_update_themes(true); + $current = $this->pre_set_site_transient_update_themes($current); + break; + } + set_site_transient($transient, $current); + } + } + + public function forced_meta_update_plugins($true = false) { + if ($this->remote_managemnet || $true) { + $this->plugins = $this->get_gitea_plugins(); + } + } + + public function forced_meta_update_themes($true = false) { + if ($this->remote_managemnet || $true) { + $this->themes = $this->get_gitea_themes(); + } + } + + public function forced_meta_update_remote_management() { + $this->forced_meta_update_plugins(); + $this->forced_meta_update_themes(); + } + + function upgrader_source_selection($source, $remote_source, $upgrader, $hook_extra = null) { + global $wp_filesystem; + + $plugin = isset($hook_extra['plugin']) ? $hook_extra['plugin'] : false; + if (isset($this->plugins[$plugin]) && $plugin) { + $new_source = trailingslashit($remote_source).dirname($plugin); + $wp_filesystem->move($source, $new_source); + return trailingslashit($new_source); + } + + return $source; + } + + function get_file_headers($contents, $type) { $gitea_headers = array( 'GiteaHost' => 'Gitea Host', @@ -127,92 +362,36 @@ class Pau_Updater { 'DomainPath' => 'Domain Path', ); - if ( false !== strpos( $type, 'plugin' ) ) { + if (false !== strpos($type, 'plugin')) { $all_headers = $default_plugin_headers; } - if ( false !== strpos( $type, 'theme' ) ) { + if (false !== strpos($type, 'theme')) { $all_headers = $default_theme_headers; } - $file_data = str_replace( "\r", "\n", $contents ); + $file_data = str_replace("\r", "\n", $contents); - $all_headers = array_merge( $gitea_headers, (array) $all_headers ); - $all_headers = array_unique( $all_headers ); + $all_headers = array_merge($gitea_headers, (array) $all_headers); + $all_headers = array_unique($all_headers); - foreach ( $all_headers as $field => $regex ) { - if ( preg_match( '/^[ \t\/*#@]*' . preg_quote( $regex, '/' ) . ':(.*)$/mi', $file_data, $match ) && $match[1] ) { - $all_headers[ $field ] = _cleanup_header_comment( $match[1] ); + foreach ($all_headers as $field => $regex) { + if (preg_match( '/^[ \t\/*#@]*'.preg_quote($regex, '/').':(.*)$/mi', $file_data, $match) && $match[1]) { + $all_headers[$field] = _cleanup_header_comment($match[1]); } else { - $all_headers[ $field ] = ''; + $all_headers[$field] = ''; } } - $all_headers = array_filter( $all_headers, - function( $e ) use ( &$all_headers ) { - return ! empty( $e ); - } ); + $all_headers = array_filter($all_headers, + function($e) use (&$all_headers) { + return !empty($e); + }); return $all_headers; } - function plugins_api( $default = false, $action, $args ) { - if ( 'plugin_information' == $action ) { - if ( isset( $this->update_data[ $args->slug ] ) ) { - $plugin = $this->update_data[ $args->slug ]; - - return (object) array( - 'name' => $plugin['name'], - 'slug' => $plugin['plugin'], - 'version' => $plugin['new_version'], - 'requires' => '4.4', - 'tested' => get_bloginfo( 'version' ), - 'last_updated' => date( 'Y-m-d' ), - 'sections' => array( - 'description' => $plugin['description'] - ) - ); - } - } - - return $default; - } - - - function set_update_data( $transient ) { - if ( empty( $transient->checked ) ) { - return $transient; - } - - foreach ( $this->update_data as $plugin => $info ) { - if ( isset( $this->active_plugins[ $plugin ] ) ) { - $plugin_data = get_plugin_data( WP_PLUGIN_DIR . '/' . $plugin ); - $version = $plugin_data['Version']; - - if ( version_compare( $version, $info['new_version'], '<' ) ) { - $transient->response[ $plugin ] = (object) $info; - } - } - } - - return $transient; - } - - - function upgrader_source_selection( $source, $remote_source, $upgrader, $hook_extra = null ) { - global $wp_filesystem; - - $plugin = isset( $hook_extra['plugin'] ) ? $hook_extra['plugin'] : false; - if ( isset( $this->update_data[ $plugin ] ) && $plugin ) { - $new_source = trailingslashit( $remote_source ) . dirname( $plugin ); - $wp_filesystem->move( $source, $new_source ); - return trailingslashit( $new_source ); - } - - return $source; - } - - function extra_plugin_headers( $headers ) { + function extra_headers($headers) { $headers[] = 'Gitea URI'; $headers[] = 'Gitea Host'; return $headers;