diff --git a/.circleci/config.yml b/.circleci/config.yml index 50eaa4f..982dd59 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -1,7 +1,7 @@ version: 2.1 -orbs: - wp-svn: studiopress/wp-svn@0.1 +# orbs: +# wp-svn: studiopress/wp-svn@0.1 jobs: test: @@ -23,16 +23,16 @@ workflows: test-deploy: jobs: - test - - approval-for-deploy-tested-up-to-bump: - type: approval - requires: - - test - filters: - tags: - ignore: /.*/ - branches: - only: /^bump-tested-up-to.*/ - - wp-svn/deploy-tested-up-to-bump: - context: genesis-svn - requires: - - approval-for-deploy-tested-up-to-bump + # - approval-for-deploy-tested-up-to-bump: + # type: approval + # requires: + # - test + # filters: + # tags: + # ignore: /.*/ + # branches: + # only: /^bump-tested-up-to.*/ + # - wp-svn/deploy-tested-up-to-bump: + # context: genesis-svn + # requires: + # - approval-for-deploy-tested-up-to-bump diff --git a/.gitignore b/.gitignore index e8c57ce..6962582 100644 --- a/.gitignore +++ b/.gitignore @@ -3,3 +3,4 @@ Thumbs.db .svn node_modules/ vendor/ +*.zip diff --git a/.nvmrc b/.nvmrc new file mode 100644 index 0000000..2edeafb --- /dev/null +++ b/.nvmrc @@ -0,0 +1 @@ +20 \ No newline at end of file diff --git a/.svnignore b/.svnignore index b74f328..cfdd0c1 100644 --- a/.svnignore +++ b/.svnignore @@ -2,4 +2,13 @@ .gitignore .gitattributes .svnignore +.nvmrc +.DS_Store +.circleci/ +package.json +package-lock.json +composer.json +composer.lock node_modules +scripts/ +*.zip \ No newline at end of file diff --git a/Gruntfile.js b/Gruntfile.js deleted file mode 100644 index e1e6b1e..0000000 --- a/Gruntfile.js +++ /dev/null @@ -1,96 +0,0 @@ -'use strict'; - -module.exports = function(grunt) { - - // Load tasks - require('load-grunt-tasks')(grunt); - - grunt.initConfig({ - pkg: grunt.file.readJSON('package.json'), - - - // Dependencies - - // PHP - - // Lint .php files for syntax errors - phplint: { - all: [ '*.php', 'lib/**/*.php' ] - }, - - - // I18n - - // Add text domain as last argument of i18n functions - addtextdomain: { - php: { - files: { - src: [ - '*.php', - 'lib/**/*.php' - ] - } - } - }, - - // Check text domain is last argument of i18n functions - checktextdomain: { - options: { - text_domain: '<%= pkg.name %>', - keywords: [ - '__:1,2d', - '_e:1,2d', - '_x:1,2c,3d', - '_ex:1,2c,3d', - '_n:1,2,4d', - '_nx:1,2,4c,5d', - '_n_noop:1,2,3d', - '_nx_noop:1,2,3c,4d', - 'esc_attr__:1,2d', - 'esc_html__:1,2d', - 'esc_attr_e:1,2d', - 'esc_html_e:1,2d', - 'esc_attr_x:1,2c,3d', - 'esc_html_x:1,2c,3d' - ] - }, - files: { - expand: true, - src: [ - '*.php', - 'lib/**/*.php' - ] - } - }, - - - // Build language .pot file - makepot: { - plugin: { - options: { - domainPath: '/languages', - processPot: function( pot ) { - pot.headers['report-msgid-bugs-to'] = 'StudioPress '; - pot.headers['last-translator'] = 'StudioPress '; - pot.headers['language-team'] = 'English '; - pot.headers['plural-forms'] = 'nplurals=2; plural=n != 1;'; - pot.headers['x-generator'] = 'grunt-wp-i18n 0.4.4'; - pot.headers['x-poedit-basepath'] = '.'; - pot.headers['x-poedit-language'] = 'English'; - pot.headers['x-poedit-country'] = 'UNITED STATES'; - pot.headers['x-poedit-sourcecharset'] = 'utf-8'; - pot.headers['x-poedit-keywordslist'] = '__;_e;_x:1,2c;_ex:1,2c;_n:1,2;_nx:1,2,4c;_n_noop:1,2;_nx_noop:1,2,3c;esc_attr__;esc_html__;esc_attr_e;esc_html_e;esc_attr_x:1,2c;esc_html_x:1,2c;'; - pot.headers['x-poedit-bookmarks'] = ''; - pot.headers['x-poedit-searchpath-0'] = '.'; - pot.headers['x-textdomain-support'] = 'yes'; - return pot; - }, - type: 'wp-plugin' - } - } - }, - - - }); - -}; diff --git a/genesis-beta-tester.php b/genesis-beta-tester.php index e8a868d..8cfcf6c 100644 --- a/genesis-beta-tester.php +++ b/genesis-beta-tester.php @@ -6,7 +6,7 @@ * Author: Nathan Rice * Author URI: http://www.nathanrice.net/ - * Version: 1.0.1 + * Version: 1.0.2 * Text Domain: genesis-beta-tester * Domain Path: /languages/ @@ -55,3 +55,17 @@ function genesis_beta_tester_activation_hook() { function genesis_beta_tester_init() { new Genesis_Beta_Tester(); } + +/** + * Initialize checking of plugin updates from WP Engine. + */ +function genesis_beta_tester_check_for_upgrades() { + $properties = array( + 'plugin_slug' => 'genesis-beta-tester', + 'plugin_basename' => plugin_basename( __FILE__ ), + ); + + require_once __DIR__ . '/includes/class-genesis-beta-tester-plugin-updater.php'; + new Genesis_Beta_Tester_Plugin_Updater( $properties ); +} +add_action( 'admin_init', 'genesis_beta_tester_check_for_upgrades' ); diff --git a/includes/class-genesis-beta-tester-plugin-updater.php b/includes/class-genesis-beta-tester-plugin-updater.php new file mode 100644 index 0000000..16cbdeb --- /dev/null +++ b/includes/class-genesis-beta-tester-plugin-updater.php @@ -0,0 +1,252 @@ +api_url = 'https://wpe-plugin-updates.wpengine.com/'; + + $this->cache_time = time() + HOUR_IN_SECONDS * 5; + + $this->properties = $this->get_full_plugin_properties( $properties, $this->api_url ); + + if ( ! $this->properties ) { + return; + } + + $this->register(); + } + + /** + * Get the full plugin properties, including the directory name, version, basename, and add a transient name. + * + * @param Properties $properties These properties are passed in when instantiating to identify the plugin and it's update location. + * @param ApiUrl $api_url The URL where the api is located. + */ + public function get_full_plugin_properties( $properties, $api_url ) { + $plugins = \get_plugins(); + + // Scan through all plugins installed and find the one which matches this one in question. + foreach ( $plugins as $plugin_basename => $plugin_data ) { + // Match using the passed-in plugin's basename. + if ( $plugin_basename === $properties['plugin_basename'] ) { + // Add the values we need to the properties. + $properties['plugin_dirname'] = dirname( $plugin_basename ); + $properties['plugin_version'] = $plugin_data['Version']; + $properties['plugin_update_transient_name'] = 'wpesu-plugin-' . sanitize_title( $properties['plugin_dirname'] ); + $properties['plugin_update_transient_exp_name'] = 'wpesu-plugin-' . sanitize_title( $properties['plugin_dirname'] ) . '-expiry'; + $properties['plugin_manifest_url'] = trailingslashit( $api_url ) . trailingslashit( $properties['plugin_slug'] ) . 'info.json'; + + return $properties; + } + } + + // No matching plugin was found installed. + return null; + } + + /** + * Register hooks. + * + * @return void + */ + public function register() { + add_filter( 'plugins_api', array( $this, 'filter_plugin_update_info' ), 20, 3 ); + add_filter( 'pre_set_site_transient_update_plugins', array( $this, 'filter_plugin_update_transient' ) ); + } + + /** + * Filter the plugin update transient to take over update notifications. + * + * @param object $transient The site_transient_update_plugins transient. + * + * @handles site_transient_update_plugins + * @return object + */ + public function filter_plugin_update_transient( $transient ) { + // No update object exists. Return early. + if ( empty( $transient ) ) { + return $transient; + } + + $result = $this->fetch_plugin_info(); + + if ( false === $result ) { + return $transient; + } + + $res = $this->parse_plugin_info( $result ); + + if ( version_compare( $this->properties['plugin_version'], $result->version, '<' ) ) { + $transient->response[ $res->plugin ] = $res; + $transient->checked[ $res->plugin ] = $result->version; + } else { + $transient->no_update[ $res->plugin ] = $res; + } + + return $transient; + } + + /** + * Filters the plugin update information. + * + * @param object $res The response to be modified for the plugin in question. + * @param string $action The action in question. + * @param object $args The arguments for the plugin in question. + * + * @handles plugins_api + * @return object + */ + public function filter_plugin_update_info( $res, $action, $args ) { + // Do nothing if this is not about getting plugin information. + if ( 'plugin_information' !== $action ) { + return $res; + } + + // Do nothing if it is not our plugin. + if ( $this->properties['plugin_dirname'] !== $args->slug ) { + return $res; + } + + $result = $this->fetch_plugin_info(); + + // Do nothing if we don't get the correct response from the server. + if ( false === $result ) { + return $res; + } + + return $this->parse_plugin_info( $result ); + } + + /** + * Fetches the plugin update object from the WP Product Info API. + * + * @return object|false + */ + private function fetch_plugin_info() { + // Fetch cache first. + $expiry = get_option( $this->properties['plugin_update_transient_exp_name'], 0 ); + $response = get_option( $this->properties['plugin_update_transient_name'] ); + + if ( empty( $expiry ) || time() > $expiry || empty( $response ) ) { + $response = wp_remote_get( + $this->properties['plugin_manifest_url'], + array( + 'timeout' => 10, + 'headers' => array( + 'Accept' => 'application/json', + ), + ) + ); + + if ( + is_wp_error( $response ) || + 200 !== wp_remote_retrieve_response_code( $response ) || + empty( wp_remote_retrieve_body( $response ) ) + ) { + return false; + } + + $response = wp_remote_retrieve_body( $response ); + + // Cache the response. + update_option( $this->properties['plugin_update_transient_exp_name'], $this->cache_time, false ); + update_option( $this->properties['plugin_update_transient_name'], $response, false ); + } + + $decoded_response = json_decode( $response ); + + if ( json_last_error() !== JSON_ERROR_NONE ) { + return false; + } + + return $decoded_response; + } + + /** + * Parses the product info response into an object that WordPress would be able to understand. + * + * @param object $response The response object. + * + * @return stdClass + */ + private function parse_plugin_info( $response ) { + + global $wp_version; + + $res = new stdClass(); + $res->name = $response->name; + $res->slug = $response->slug; + $res->version = $response->version; + $res->requires = $response->requires; + $res->download_link = $response->download_link; + $res->trunk = $response->download_link; + $res->new_version = $response->version; + $res->plugin = $this->properties['plugin_basename']; + $res->package = $response->download_link; + + // Plugin information modal and core update table use a strict version comparison, which is weird. + // If we're genuinely not compatible with the point release, use our WP tested up to version. + // otherwise use exact same version as WP to avoid false positive. + $res->tested = 1 === version_compare( substr( $wp_version, 0, 3 ), $response->tested ) + ? $response->tested + : $wp_version; + + $res->sections = array( + 'description' => $response->sections->description, + 'changelog' => $response->sections->changelog, + ); + + return $res; + } +} diff --git a/languages/genesis-beta-tester.pot b/languages/genesis-beta-tester.pot index 1234fcf..8f2986d 100644 --- a/languages/genesis-beta-tester.pot +++ b/languages/genesis-beta-tester.pot @@ -1,49 +1,50 @@ -# Copyright (C) 2019 Nathan Rice +# Copyright (C) 2024 Nathan Rice # This file is distributed under the GNU General Public License v2.0 (or later). msgid "" msgstr "" -"Project-Id-Version: Genesis Beta Tester 1.0.0\n" -"Report-Msgid-Bugs-To: " -"https://wordpress.org/support/plugin/genesis-beta-tester\n" -"POT-Creation-Date: 2019-07-02 19:02:36+00:00\n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=utf-8\n" -"Content-Transfer-Encoding: 8bit\n" -"PO-Revision-Date: 2019-MO-DA HO:MI+ZONE\n" +"Project-Id-Version: Genesis Beta Tester 1.0.2\n" +"Report-Msgid-Bugs-To: StudioPress \n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" -"X-Generator: node-wp-i18n 1.2.3\n" - -#: genesis-beta-tester.php:31 -#. Translators: The string is a url to the genesis framework. -msgid "" -"Sorry, you can't activate unless you have installed Genesis" -msgstr "" - -#: genesis-beta-tester.php:37 -#. Translators: The string is the lowest version of Genesis needed to activate. -msgid "Sorry, you cannot activate without Genesis %s or greater" -msgstr "" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"POT-Creation-Date: 2024-10-14T12:51:08+00:00\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"X-Generator: WP-CLI 2.10.0\n" +"X-Domain: genesis-beta-tester\n" -#. Plugin Name of the plugin/theme +#. Plugin Name of the plugin +#: genesis-beta-tester.php msgid "Genesis Beta Tester" msgstr "" -#. Plugin URI of the plugin/theme +#. Plugin URI of the plugin +#: genesis-beta-tester.php msgid "http://www.studiopress.com/plugins/genesis-beta-tester" msgstr "" -#. Description of the plugin/theme -msgid "" -"Genesis Beta Tester lets you one-click update to the latest version of " -"Genesis, even if it is still in beta." +#. Description of the plugin +#: genesis-beta-tester.php +msgid "Genesis Beta Tester lets you one-click update to the latest version of Genesis, even if it is still in beta." msgstr "" -#. Author of the plugin/theme +#. Author of the plugin +#: genesis-beta-tester.php msgid "Nathan Rice" msgstr "" -#. Author URI of the plugin/theme +#. Author URI of the plugin +#: genesis-beta-tester.php msgid "http://www.nathanrice.net/" -msgstr "" \ No newline at end of file +msgstr "" + +#. Translators: The string is a url to the genesis framework. +#: genesis-beta-tester.php:31 +msgid "Sorry, you can't activate unless you have installed Genesis" +msgstr "" + +#. Translators: The string is the lowest version of Genesis needed to activate. +#: genesis-beta-tester.php:37 +msgid "Sorry, you cannot activate without Genesis %s or greater" +msgstr "" diff --git a/package-lock.json b/package-lock.json index be91cce..b6350b3 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,221 +1,53 @@ { "name": "genesis-beta-tester", + "lockfileVersion": 3, "requires": true, - "lockfileVersion": 1, - "dependencies": { - "balanced-match": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", - "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", - "dev": true - }, - "bluebird": { - "version": "3.5.5", - "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.5.5.tgz", - "integrity": "sha512-5am6HnnfN+urzt4yfg7IgTbotDjIT/u8AJpEt0sIU9FtXfVeezXAPKswrG+xKUCOYAINpSdgZVDU6QFh+cuH3w==", - "dev": true - }, - "brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dev": true, - "requires": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" + "packages": { + "": { + "name": "genesis-beta-tester", + "devDependencies": { + "adm-zip": "^0.5.16", + "minimatch": "^10.0.1" } }, - "concat-map": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", - "dev": true - }, - "encoding": { - "version": "0.1.12", - "resolved": "https://registry.npmjs.org/encoding/-/encoding-0.1.12.tgz", - "integrity": "sha1-U4tm8+5izRq1HsMjgp0flIDHS+s=", + "node_modules/adm-zip": { + "version": "0.5.16", + "resolved": "https://registry.npmjs.org/adm-zip/-/adm-zip-0.5.16.tgz", + "integrity": "sha512-TGw5yVi4saajsSEgz25grObGHEUaDrniwvA2qwSC060KfqGPdglhvPMA2lPIoxs3PQIItj2iag35fONcQqgUaQ==", "dev": true, - "requires": { - "iconv-lite": "~0.4.13" + "engines": { + "node": ">=12.0" } }, - "fs.realpath": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", - "dev": true - }, - "gettext-parser": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/gettext-parser/-/gettext-parser-3.1.1.tgz", - "integrity": "sha512-vNhWcqXEtZPs5Ft1ReA34g7ByWotpcOIeJvXVy2jF3/G2U9v6W0wG4Z4hXzcU8R//jArqkgHcVCGgGqa4vxVlQ==", - "dev": true, - "requires": { - "encoding": "^0.1.12", - "readable-stream": "^3.2.0", - "safe-buffer": "^5.1.2" - }, - "dependencies": { - "readable-stream": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.4.0.tgz", - "integrity": "sha512-jItXPLmrSR8jmTRmRWJXCnGJsfy85mB3Wd/uINMXA65yrnFo0cPClFIUWzo2najVNSl+mx7/4W8ttlLWJe99pQ==", - "dev": true, - "requires": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - } - } - } - }, - "glob": { - "version": "7.1.4", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.4.tgz", - "integrity": "sha512-hkLPepehmnKk41pUGm3sYxoFs/umurYfYJCerbXEyFIWcAzvpipAgVkBqqT9RBKMGjnq6kMuyYwha6csxbiM1A==", - "dev": true, - "requires": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.4", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - } - }, - "iconv-lite": { - "version": "0.4.24", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", - "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", - "dev": true, - "requires": { - "safer-buffer": ">= 2.1.2 < 3" - } - }, - "inflight": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", - "dev": true, - "requires": { - "once": "^1.3.0", - "wrappy": "1" - } - }, - "inherits": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", - "dev": true - }, - "lodash": { - "version": "4.17.21", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", - "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", - "dev": true - }, - "minimatch": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", - "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", - "dev": true, - "requires": { - "brace-expansion": "^1.1.7" - } - }, - "minimist": { - "version": "1.2.6", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.6.tgz", - "integrity": "sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q==", - "dev": true - }, - "mkdirp": { - "version": "0.5.5", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz", - "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==", - "dev": true, - "requires": { - "minimist": "^1.2.5" - } - }, - "node-wp-i18n": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/node-wp-i18n/-/node-wp-i18n-1.2.3.tgz", - "integrity": "sha512-YMzMcsjXbGYDB9vHyb289CYXAGmXhcNLbeTlOnWgPNkZd9xrovcbRd7cQyKd9BQHOjS7Nw8WCbJ7nvtR7rc0rg==", - "dev": true, - "requires": { - "bluebird": "^3.4.1", - "gettext-parser": "^3.1.0", - "glob": "^7.0.5", - "lodash": "^4.14.2", - "minimist": "^1.2.0", - "mkdirp": "^0.5.1", - "tmp": "^0.0.33" - } - }, - "once": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", - "dev": true, - "requires": { - "wrappy": "1" - } - }, - "os-tmpdir": { + "node_modules/balanced-match": { "version": "1.0.2", - "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", - "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=", - "dev": true - }, - "path-is-absolute": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", "dev": true }, - "safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "dev": true - }, - "safer-buffer": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", - "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", - "dev": true - }, - "string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", "dev": true, - "requires": { - "safe-buffer": "~5.1.0" + "dependencies": { + "balanced-match": "^1.0.0" } }, - "tmp": { - "version": "0.0.33", - "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", - "integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==", + "node_modules/minimatch": { + "version": "10.0.1", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.0.1.tgz", + "integrity": "sha512-ethXTt3SGGR+95gudmqJ1eNhRO7eGEGIgYA9vnPatK4/etz2MEVDno5GMCibdMTuBMyElzIlgxMna3K94XDIDQ==", "dev": true, - "requires": { - "os-tmpdir": "~1.0.2" + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": "20 || >=22" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" } - }, - "util-deprecate": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", - "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", - "dev": true - }, - "wrappy": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", - "dev": true } } } diff --git a/package.json b/package.json index c809d22..6c6c345 100644 --- a/package.json +++ b/package.json @@ -6,12 +6,12 @@ "url": "https://github.com/copyblogger/genesis-beta-tester" }, "dependencies": {}, - "devDependencies": { - "node-wp-i18n": "^1.2.3" - }, "scripts": { - "makepot": "wpi18n makepot --exclude=vendor,node_modules", - "addtextdomain": "wpi18n addtextdomain --exclude=vendor,node_modules" + "zip": "node scripts/create-zip.js" + }, + "devDependencies": { + "adm-zip": "^0.5.16", + "minimatch": "^10.0.1" }, "plugin": { "name": "Genesis Beta Tester", @@ -19,7 +19,7 @@ "description": "Genesis Beta Tester lets you one-click update to the latest version of Genesis, even if it is still in beta.", "author": "StudioPress", "authoruri": "http://www.studiopress.com/", - "version": "1.0.1", + "version": "1.0.2", "license": "GPL-2.0+", "licenseuri": "http://www.gnu.org/licenses/gpl-2.0.html", "textdomain": "genesis-beta-tester" diff --git a/readme.txt b/readme.txt index b2ad941..5279c30 100644 --- a/readme.txt +++ b/readme.txt @@ -3,8 +3,8 @@ Contributors: nathanrice, studiopress, wpmuguru Donate link: https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=5553118 Tags: genesis, genesiswp, studiopress Requires at least: 3.9 -Tested up to: 6.3 -Stable tag: 1.0.1 +Tested up to: 6.6 +Stable tag: 1.0.2 This plugin lets you one-click update to the latest Genesis release, even if it's still in beta. @@ -30,6 +30,9 @@ If you activate the plugin and do not see the update notification, that likely m == Changelog == += 1.0.2 = +* Genesis Beta Tester now uses its own update mechanism from WP Engine servers. + = 1.0.1 = * Test with latest WordPress version diff --git a/scripts/create-zip.js b/scripts/create-zip.js new file mode 100644 index 0000000..a9e0931 --- /dev/null +++ b/scripts/create-zip.js @@ -0,0 +1,82 @@ +const fs = require("fs"); +const path = require("path"); +const AdmZip = require("adm-zip"); +const { minimatch } = require("minimatch"); +const { execSync } = require("child_process"); + +function getPluginVersion() { + const pluginFile = fs.readFileSync("genesis-beta-tester.php", "utf8"); + const versionMatch = pluginFile.match(/Version:\s*(.+)/); + return versionMatch ? versionMatch[1].trim() : "unknown"; +} + +function getIgnorePatterns() { + const distignore = fs.readFileSync(".svnignore", "utf8"); + return distignore + .split("\n") + .map((line) => line.trim()) + .filter((line) => line && !line.startsWith("#")) + .map((pattern) => `*${pattern}*`); +} + +function shouldIgnore(filePath, ignorePatterns) { + const relativePath = path.relative(process.cwd(), filePath); + return ignorePatterns.some((pattern) => + minimatch(relativePath, pattern, { matchBase: true, dot: true }) + ); +} + +function runBuildSteps() { + console.log("Running build steps..."); + + try { + console.log("Generating language file..."); + execSync( + "wp i18n make-pot . languages/genesis-beta-tester.pot --exclude=config,node_modules,scripts,vendor --headers='{ \"Report-Msgid-Bugs-To\": \"StudioPress \" }' --exclude=bin/ --quiet", + { stdio: "inherit" } + ); + console.log("Build steps completed successfully."); + } catch (error) { + console.error("Error during build steps:", error); + process.exit(1); + } +} + +function createZip() { + runBuildSteps(); + + const version = getPluginVersion(); + const ignorePatterns = getIgnorePatterns(); + const zipFileName = `genesis-beta-tester.${version}.zip`; + + const zip = new AdmZip(); + + function addDirectoryToZip(directory) { + const files = fs.readdirSync(directory); + for (const file of files) { + const filePath = path.join(directory, file); + const stats = fs.statSync(filePath); + const relativePath = path.relative(process.cwd(), filePath); + + if (shouldIgnore(filePath, ignorePatterns)) { + continue; + } + + if (stats.isDirectory()) { + addDirectoryToZip(filePath); + } else { + zip.addFile( + path.join("genesis-beta-tester", relativePath), + fs.readFileSync(filePath) + ); + } + } + } + + addDirectoryToZip(process.cwd()); + + zip.writeZip(zipFileName); + console.log(`Created ${zipFileName}`); +} + +createZip();