diff --git a/.editorconfig b/.editorconfig index c520deaaf..6780193cd 100644 --- a/.editorconfig +++ b/.editorconfig @@ -10,3 +10,6 @@ indent_size = 4 [*.{json,yml,md}] indent_style = space indent_size = 2 + +[{*.txt,wp-config-sample.php}] +end_of_line = crlf diff --git a/.gitattributes b/.gitattributes index 99484cbc3..5cd2d40ce 100644 --- a/.gitattributes +++ b/.gitattributes @@ -1,3 +1,12 @@ /.github export-ignore /.gitattributes export-ignore /.gitignore export-ignore +/.wordpress-version-checker.json export-ignore + +# Text files should have LF line endings. +* text eol=lf + +# Binary files should not be modified. +*.mo binary +*.png binary +*.jpg binary diff --git a/.github/workflows/wordpress-latest.yml b/.github/workflows/wordpress-version-checker.yml similarity index 80% rename from .github/workflows/wordpress-latest.yml rename to .github/workflows/wordpress-version-checker.yml index b134ea59d..34e44107a 100644 --- a/.github/workflows/wordpress-latest.yml +++ b/.github/workflows/wordpress-version-checker.yml @@ -10,11 +10,14 @@ on: schedule: - cron: '0 0 * * 1' +permissions: + issues: write + jobs: wordpress-version-checker: runs-on: ubuntu-latest steps: - name: WordPress version checker - uses: skaut/wordpress-version-checker@v1.2.0 + uses: skaut/wordpress-version-checker@master with: repo-token: ${{ secrets.GITHUB_TOKEN }} diff --git a/.wordpress-version-checker.json b/.wordpress-version-checker.json new file mode 100644 index 000000000..9aa58aa0c --- /dev/null +++ b/.wordpress-version-checker.json @@ -0,0 +1,4 @@ +{ + "readme": "readme.txt", + "channel": "rc" +} diff --git a/CHANGELOG.md b/CHANGELOG.md index 299dfb4f3..e95fe682c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,7 +7,7 @@ All notable changes to this project will be documented in this file, per [the Ke ## [2.0.0] - TBD **Note that Distributor now requires PHP 7.4 or later and WordPress 5.7 or later.** -_This entry was generated for the 2.0.0-rc1 release and will be updated during the Beta and Release Candidate processes._ +Please see the [migration guide](https://10up.github.io/distributor/tutorial-migration-guide-version-1-to-version-2.html) for important changes between version 1 and version 2 that may require your action. ### Added - Migration guide for version 1 to version 2 (props [@peterwilsoncc](https://github.com/peterwilsoncc), [@faisal-alvi](https://github.com/faisal-alvi), [@jeffpaul](https://github.com/jeffpaul) via [#996](https://github.com/10up/distributor/pull/996)). @@ -30,12 +30,13 @@ _This entry was generated for the 2.0.0-rc1 release and will be updated during t - Toggles the Distributor admin bar element in Gutenberg based on the post status (props [@ggutenberg](https://github.com/ggutenberg), [@jeffpaul](https://github.com/jeffpaul), [@peterwilsoncc](https://github.com/peterwilsoncc) via [#1022](https://github.com/10up/distributor/pull/1022), [#1114](https://github.com/10up/distributor/pull/1114)). - Reduced duplicate code pushing posts to connections (props [@peterwilsoncc](https://github.com/peterwilsoncc), [@cadic](https://github.com/cadic), [@jeffpaul](https://github.com/jeffpaul), [@faisal-alvi](https://github.com/faisal-alvi), [@aaronware](https://github.com/aaronware) via [#999](https://github.com/10up/distributor/pull/999)). - Unified translator comments (props [@peterwilsoncc](https://github.com/peterwilsoncc), [@cadic](https://github.com/cadic) via [#949](https://github.com/10up/distributor/pull/949)). -- WordPress "tested up to" version 6.2 (props [@jayedul](https://github.com/jayedul), [@faisal-alvi](https://github.com/faisal-alvi), [@jeffpaul](https://github.com/jeffpaul) via [#1047](https://github.com/10up/distributor/pull/1047)). +- WordPress "tested up to" version 6.3 (props [@jayedul](https://github.com/jayedul), [@faisal-alvi](https://github.com/faisal-alvi), [@jeffpaul](https://github.com/jeffpaul), [@dkotter](https://github.com/dkotter) via [#1047](https://github.com/10up/distributor/pull/1047), [#1123](https://github.com/10up/distributor/pull/1123)). - Browserlist database updated to version 1.0.30001489 (props [@peterwilsoncc](https://github.com/peterwilsoncc), [@dkotter](https://github.com/dkotter) via [#1059](https://github.com/10up/distributor/pull/1059)). - Build process now uses `@wordpress/scripts` in place of Gulp (props [@peterwilsoncc](https://github.com/peterwilsoncc), [@dinhtungdu](https://github.com/dinhtungdu), [@dkotter](https://github.com/dkotter) via [#916](https://github.com/10up/distributor/pull/916)). - Migrated E2E tests to Cypress (props [@peterwilsoncc](https://github.com/peterwilsoncc), [@jeffpaul](https://github.com/jeffpaul), [@iamdharmesh](https://github.com/iamdharmesh) via [#1070](https://github.com/10up/distributor/pull/1070)). - Update `dependency-review.yml` (props [@jeffpaul](https://github.com/jeffpaul), [@peterwilsoncc](https://github.com/peterwilsoncc) via [#1054](https://github.com/10up/distributor/pull/1054)). - Order of operations setting meta, media and terms in the network push and pull functions (props [@sethrubenstein](https://github.com/sethrubenstein), [@jeffpaul](https://github.com/jeffpaul), [@peterwilsoncc](https://github.com/peterwilsoncc) via [#1095](https://github.com/10up/distributor/pull/1095)). +- Upgrade the Plugin Update Checker library from 4.13 to 5.1 (props [@dkotter](https://github.com/dkotter) via [#1124](https://github.com/10up/distributor/pull/1124)). ### Deprecated - `dt_push_post` action hook (props [@dkotter](https://github.com/dkotter), [@peterwilsoncc](https://github.com/peterwilsoncc), [@dhanendran](https://github.com/dhanendran), [@ravinderk](https://github.com/ravinderk), [@jeffpaul](https://github.com/jeffpaul) via [#1024](https://github.com/10up/distributor/pull/1024)). @@ -470,7 +471,7 @@ This adds a post type selector when viewing the Pull Content list for both exter - Initial closed release. [Unreleased]: https://github.com/10up/distributor/compare/trunk...develop -[2.0.0]: https://github.com/10up/distributor/compare/1.9.1...develop +[2.0.0]: https://github.com/10up/distributor/compare/1.9.1...2.0.0 [1.9.1]: https://github.com/10up/distributor/compare/1.9.0...1.9.1 [1.9.0]: https://github.com/10up/distributor/compare/1.8.0...1.9.0 [1.8.0]: https://github.com/10up/distributor/compare/1.7.1...1.8.0 diff --git a/README.md b/README.md index 17ba03ee7..613482d23 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,7 @@ > Distributor is a WordPress plugin that makes it easy to distribute and reuse content across your websites — whether in a single multisite or across the web. -[![Support Level](https://img.shields.io/badge/support-active-green.svg)](#support-level) [![Tests](https://github.com/10up/distributor/actions/workflows/test.yml/badge.svg)](https://github.com/10up/distributor/actions/workflows/test.yml) [![Linting](https://github.com/10up/distributor/actions/workflows/lint.yml/badge.svg)](https://github.com/10up/distributor/actions/workflows/lint.yml) [![Code scanning](https://github.com/10up/distributor/actions/workflows/codeql-analysis.yml/badge.svg)](https://github.com/10up/distributor/actions/workflows/codeql-analysis.yml) [![Release Version](https://img.shields.io/github/release/10up/distributor.svg)](https://github.com/10up/distributor/releases/latest) ![WordPress tested up to version](https://img.shields.io/badge/WordPress-v6.1%20tested-success.svg) [![License](https://img.shields.io/github/license/10up/distributor.svg)](https://github.com/10up/distributor/blob/develop/LICENSE.md) +[![Support Level](https://img.shields.io/badge/support-active-green.svg)](#support-level) [![Tests](https://github.com/10up/distributor/actions/workflows/test.yml/badge.svg)](https://github.com/10up/distributor/actions/workflows/test.yml) [![Linting](https://github.com/10up/distributor/actions/workflows/lint.yml/badge.svg)](https://github.com/10up/distributor/actions/workflows/lint.yml) [![Code scanning](https://github.com/10up/distributor/actions/workflows/codeql-analysis.yml/badge.svg)](https://github.com/10up/distributor/actions/workflows/codeql-analysis.yml) [![Release Version](https://img.shields.io/github/release/10up/distributor.svg)](https://github.com/10up/distributor/releases/latest) ![WordPress tested up to version](https://img.shields.io/badge/WordPress-v6.3%20tested-success.svg) [![License](https://img.shields.io/github/license/10up/distributor.svg)](https://github.com/10up/distributor/blob/develop/LICENSE.md) *You can learn more about Distributor's features at [DistributorPlugin.com](https://distributorplugin.com) and documentation at the [Distributor documentation site](https://10up.github.io/distributor/).* @@ -58,7 +58,7 @@ Distributor is built with the same extensible approach as WordPress itself, with * [WordPress](http://wordpress.org) 5.7+ * External connections require HTTP Basic Authentication or [WordPress.com OAuth2](https://developer.wordpress.com/docs/oauth2/) (must be on [WordPress VIP](https://wpvip.com/)) be set up on the remote website. For Basic Auth, we recommend using [Application Passwords](https://make.wordpress.org/core/2020/11/05/application-passwords-integration-guide/#Getting-Credentials) built in to WordPress. * For external connections, Distributor needs to be installed on BOTH sides of the connection. -* Version 2 of Distributor requires version two on BOTH sides of all connections. +* Version 2.0.0 of Distributor requires version 2.0.0 on BOTH sides of all connections. For other version 2.0.0 specific changes, please see our [migration guide](https://10up.github.io/distributor/tutorial-migration-guide-version-1-to-version-2.html). ## Installation diff --git a/composer.json b/composer.json index c33347bbc..f371bd3cf 100644 --- a/composer.json +++ b/composer.json @@ -12,7 +12,7 @@ ], "require": { "php": ">=7.4", - "yahnis-elsts/plugin-update-checker": "4.13", + "yahnis-elsts/plugin-update-checker": "5.1", "ext-json": "*" }, "autoload": { diff --git a/composer.lock b/composer.lock index e297a9674..3a19644d9 100644 --- a/composer.lock +++ b/composer.lock @@ -4,30 +4,30 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "55cabc5871a7166db51644beffc3ac94", + "content-hash": "9b7761af5ca3d71ef2395537f531b6ab", "packages": [ { "name": "yahnis-elsts/plugin-update-checker", - "version": "v4.13", + "version": "v5.1", "source": { "type": "git", "url": "https://github.com/YahnisElsts/plugin-update-checker.git", - "reference": "6eb27a6911e0e0880d09e5b11f577d3f688f7da7" + "reference": "48b03e93c9c2587f9276dce00ce2b6d94c1190d2" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/YahnisElsts/plugin-update-checker/zipball/6eb27a6911e0e0880d09e5b11f577d3f688f7da7", - "reference": "6eb27a6911e0e0880d09e5b11f577d3f688f7da7", + "url": "https://api.github.com/repos/YahnisElsts/plugin-update-checker/zipball/48b03e93c9c2587f9276dce00ce2b6d94c1190d2", + "reference": "48b03e93c9c2587f9276dce00ce2b6d94c1190d2", "shasum": "" }, "require": { "ext-json": "*", - "php": ">=5.2.0" + "php": ">=5.6.20" }, "type": "library", "autoload": { "files": [ - "load-v4p13.php" + "load-v5p1.php" ] }, "notification-url": "https://packagist.org/downloads/", @@ -38,7 +38,7 @@ { "name": "Yahnis Elsts", "email": "whiteshadow@w-shadow.com", - "homepage": "http://w-shadow.com/", + "homepage": "https://w-shadow.com/", "role": "Developer" } ], @@ -52,9 +52,9 @@ ], "support": { "issues": "https://github.com/YahnisElsts/plugin-update-checker/issues", - "source": "https://github.com/YahnisElsts/plugin-update-checker/tree/v4.13" + "source": "https://github.com/YahnisElsts/plugin-update-checker/tree/v5.1" }, - "time": "2022-07-29T12:36:25+00:00" + "time": "2023-05-20T11:55:43+00:00" } ], "packages-dev": [ diff --git a/distributor.php b/distributor.php index e031d2a56..76505a34b 100644 --- a/distributor.php +++ b/distributor.php @@ -4,7 +4,7 @@ * Plugin URI: https://github.com/10up/distributor * Update URI: https://distributorplugin.com * Description: Makes it easy to distribute and reuse content across your websites, whether inside of a multisite or across the web. - * Version: 2.0.0-rc1 + * Version: 2.0.0 * Requires at least: 5.7 * Requires PHP: 7.4 * Author: 10up Inc. @@ -28,7 +28,7 @@ exit; // Exit if accessed directly. } -define( 'DT_VERSION', '2.0.0-rc1' ); +define( 'DT_VERSION', '2.0.0' ); define( 'DT_PLUGIN_FILE', preg_replace( '#^.*plugins/(.*)$#i', '$1', __FILE__ ) ); define( 'DT_PLUGIN_PATH', plugin_dir_path( __FILE__ ) ); define( 'DT_PLUGIN_FULL_FILE', __FILE__ ); diff --git a/docs/migration-guide-version-1-to-version-2.md b/docs/migration-guide-version-1-to-version-2.md index c9436f447..34c17f540 100644 --- a/docs/migration-guide-version-1-to-version-2.md +++ b/docs/migration-guide-version-1-to-version-2.md @@ -1,10 +1,10 @@ -Version 2 of Distributor includes a number of breaking changes that will require updates to custom code you may have written for distributor. +Version 2.0.0 of Distributor includes a number of breaking changes that will require updates to custom code you may have written for distributor. -## External connections require a minimum of version 2.0 +## External connections require a minimum of version 2.0.0 It is recommended that both ends of an external connection run the same version of Distributor. -Version 2.0 of Distributor will prevent the pulling of posts from sites running Version 1.9.x or lower of Distributor. +Version 2.0.0 of Distributor will prevent the pulling of posts from sites running Version 1.9.x or lower of Distributor. ### Remove canonical links for both Internal and External Connections @@ -27,3 +27,32 @@ add_action( 'plugins_loaded', function() { remove_filter( 'wpseo_canonical', '\\Distributor\\Hooks\\wpseo_canonical', 10, 2 ); } ); ``` + +### REST API Changes + +The distributor REST API endpoint at `/wp/v2/distributor/list-pull-content` has been modified substantially and will now reject connections from 1.x versions of Distributor. + +The fields returned by the endpoint have been modified to match the names used by `wp_insert_post` and `wp_update_post`. + +#### Additional parameters + +* `include` (Array|Int): Ensure result set includes specific Post IDs. Default empty. +* `order` (`asc`|`desc`): Specify order of returned data. Default `desc`. +* `orderby` (`author`|`date`|`id`|`include`|`modified`|`parent`|`relevance`|`slug`|`title`): Field to order results by. Default `date`, `relevance` for search queries. + +#### Modified parameters + +* `post_type` (String|String[]): Modified to accept multiple post types. Post types are limited to posts the connected account can edit, are public post types and visible in the WordPress REST API's standard endpoints. Default `post`. +* `post_status` (String|String[]): Modified to accept multiple post statuses. Statuses are limited to public statuses only. Default `publish`. + +### `dt_push_post` action deprecated + +The `dt_push_post` action has been deprecated in favor of two actions: `dt_push_external_post` and `dt_push_network_post`. + +Extenders using the old action are advised to switch to the new actions as a matter of priority. The deprecated action had conflicting arguments so can not be relied upon to pass data consistently. + +### Internationalization improvements + +The generation of translation files has been updated to include strings included in JavaScript files. + +Version 2.0.0 of Distributor has also improved pluralization of strings and combined similar strings to reduce the burden on translators. diff --git a/includes/bootstrap.php b/includes/bootstrap.php index 43cab6c6f..70b8bb3f3 100644 --- a/includes/bootstrap.php +++ b/includes/bootstrap.php @@ -12,6 +12,8 @@ namespace Distributor; +use YahnisElsts\PluginUpdateChecker\v5\PucFactory; + /** * PSR-4 autoloading */ @@ -130,7 +132,7 @@ function() { } ); -if ( class_exists( '\\Puc_v4_Factory' ) ) { +if ( class_exists( '\\YahnisElsts\PluginUpdateChecker\v5\PucFactory' ) ) { /** * Enable updates if we have a valid license */ @@ -144,7 +146,7 @@ function() { if ( $valid_license ) { // @codingStandardsIgnoreStart - $updateChecker = \Puc_v4_Factory::buildUpdateChecker( + $updateChecker = PucFactory::buildUpdateChecker( 'https://github.com/10up/distributor/', DT_PLUGIN_FULL_FILE, 'distributor' @@ -174,7 +176,9 @@ function( $transient ) use ( $updateChecker ) { $update = $updateChecker->getUpdateState()->getUpdate(); // Adding the plugin info to the `no_update` property is required // for the enable/disable auto-updates links to correctly appear in UI. - $transient->no_update[ $update->filename ] = $update; + if ( $update ) { + $transient->no_update[ $update->filename ] = $update; + } } return $transient; diff --git a/includes/classes/ExternalConnections/WordPressExternalConnection.php b/includes/classes/ExternalConnections/WordPressExternalConnection.php index 3668dd179..99cf8d086 100644 --- a/includes/classes/ExternalConnections/WordPressExternalConnection.php +++ b/includes/classes/ExternalConnections/WordPressExternalConnection.php @@ -276,7 +276,7 @@ public function remote_post( $url = '', $args = array() ) { && isset( $response_headers['x-distributor'] ) && ( ! isset( $response_headers['x-distributor-version'] ) - || version_compare( $response_headers['x-distributor-version'], '2.0.0-alpha', '<' ) + || version_compare( $response_headers['x-distributor-version'], '2.0.0', '<' ) ) ) { $version_error = new \WP_Error(); diff --git a/includes/rest-api.php b/includes/rest-api.php index 3ad3469eb..2445df0a5 100644 --- a/includes/rest-api.php +++ b/includes/rest-api.php @@ -379,7 +379,7 @@ function get_pull_content_permissions( $request ) { && null !== $request->get_param( 'distributor_request' ) && ( null === $request->get_header( 'X-Distributor-Version' ) - || version_compare( $request->get_header( 'X-Distributor-Version' ), '2.0.0-alpha', '<' ) + || version_compare( $request->get_header( 'X-Distributor-Version' ), '2.0.0', '<' ) ) ) { return new \WP_Error( diff --git a/package-lock.json b/package-lock.json index fb17111ca..e81390a68 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "distributor", - "version": "2.0.0-rc.1", + "version": "2.0.0", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "distributor", - "version": "2.0.0-rc.1", + "version": "2.0.0", "license": "GPL-2.0-or-later", "dependencies": { "mustache": "^4.2.0" diff --git a/package.json b/package.json index 293d85be0..d3b555540 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "distributor", - "version": "2.0.0-rc.1", + "version": "2.0.0", "description": "Distributor is a WordPress plugin that makes it easy to distribute and reuse content across your websites — whether in a single multisite or across the web.", "author": { "name": "10up", diff --git a/readme.txt b/readme.txt index 891a60f3a..f91f92d2e 100644 --- a/readme.txt +++ b/readme.txt @@ -2,9 +2,9 @@ Contributors: 10up Tags: content, distribution, syndication, management Requires at least: 5.7 -Tested up to: 6.2 +Tested up to: 6.3 Requires PHP: 7.4 -Stable tag: 1.9.1 +Stable tag: 2.0.0 License: GPLv2 or later License URI: http://www.gnu.org/licenses/gpl-2.0.html diff --git a/tests/cypress/config.js b/tests/cypress/config.js index 54b11bad6..103de3a39 100644 --- a/tests/cypress/config.js +++ b/tests/cypress/config.js @@ -2,6 +2,7 @@ const { defineConfig } = require( 'cypress' ); const { readConfig } = require( '@wordpress/env/lib/config' ); module.exports = defineConfig( { + chromeWebSecurity: false, fixturesFolder: 'tests/cypress/fixtures', screenshotsFolder: 'tests/cypress/screenshots', videosFolder: 'tests/cypress/videos', diff --git a/tests/php/bootstrap.php b/tests/php/bootstrap.php index 9ebbc224d..87309de9f 100644 --- a/tests/php/bootstrap.php +++ b/tests/php/bootstrap.php @@ -10,7 +10,7 @@ WP_Mock::bootstrap(); define( 'DT_PLUGIN_PATH', dirname( __DIR__, 2 ) ); -define( 'DT_VERSION', '2.0.0-rc1' ); +define( 'DT_VERSION', '2.0.0' ); require_once __DIR__ . '/includes/common.php'; require_once __DIR__ . '/includes/TestCase.php'; diff --git a/vendor/yahnis-elsts/plugin-update-checker/.gitattributes b/vendor/yahnis-elsts/plugin-update-checker/.gitattributes new file mode 100644 index 000000000..c5fffccc7 --- /dev/null +++ b/vendor/yahnis-elsts/plugin-update-checker/.gitattributes @@ -0,0 +1 @@ +/build export-ignore diff --git a/vendor/yahnis-elsts/plugin-update-checker/Puc/v4/Factory.php b/vendor/yahnis-elsts/plugin-update-checker/Puc/v4/Factory.php deleted file mode 100644 index 00001d9cd..000000000 --- a/vendor/yahnis-elsts/plugin-update-checker/Puc/v4/Factory.php +++ /dev/null @@ -1,6 +0,0 @@ -rootDir = dirname(__FILE__) . '/'; - - if ( version_compare(PHP_VERSION, '5.3', '>=') && __NAMESPACE__ ) { - $namespaceWithSlash = __NAMESPACE__ . '\\'; - } else { - $namespaceWithSlash = ''; - } - - $nameParts = explode('_', substr(__CLASS__, strlen($namespaceWithSlash)), 3); - $this->prefix = $namespaceWithSlash . $nameParts[0] . '_' . $nameParts[1] . '_'; - - $this->libraryDir = $this->rootDir . '../..'; - if ( !self::isPhar() ) { - $this->libraryDir = realpath($this->libraryDir); - } - $this->libraryDir = $this->libraryDir . '/'; - - $this->staticMap = array( - $namespaceWithSlash . 'PucReadmeParser' => 'vendor/PucReadmeParser.php', - $namespaceWithSlash . 'Parsedown' => 'vendor/Parsedown.php', - $namespaceWithSlash . 'Puc_v4_Factory' => 'Puc/v4/Factory.php', - ); - - spl_autoload_register(array($this, 'autoload')); - } - - /** - * Determine if this file is running as part of a Phar archive. - * - * @return bool - */ - private static function isPhar() { - //Check if the current file path starts with "phar://". - static $pharProtocol = 'phar://'; - return (substr(__FILE__, 0, strlen($pharProtocol)) === $pharProtocol); - } - - public function autoload($className) { - if ( isset($this->staticMap[$className]) && file_exists($this->libraryDir . $this->staticMap[$className]) ) { - /** @noinspection PhpIncludeInspection */ - include ($this->libraryDir . $this->staticMap[$className]); - return; - } - - if (strpos($className, $this->prefix) === 0) { - $path = substr($className, strlen($this->prefix)); - $path = str_replace('_', '/', $path); - $path = $this->rootDir . $path . '.php'; - - if (file_exists($path)) { - /** @noinspection PhpIncludeInspection */ - include $path; - } - } - } - } - -endif; diff --git a/vendor/yahnis-elsts/plugin-update-checker/Puc/v4p13/DebugBar/PluginExtension.php b/vendor/yahnis-elsts/plugin-update-checker/Puc/v4p13/DebugBar/PluginExtension.php deleted file mode 100644 index 2514a043a..000000000 --- a/vendor/yahnis-elsts/plugin-update-checker/Puc/v4p13/DebugBar/PluginExtension.php +++ /dev/null @@ -1,33 +0,0 @@ -updateChecker->getUniqueName('uid') ) { - return; - } - $this->preAjaxRequest(); - $info = $this->updateChecker->requestInfo(); - if ( $info !== null ) { - echo 'Successfully retrieved plugin info from the metadata URL:'; - echo '
', htmlentities(print_r($info, true)), '
'; - } else { - echo 'Failed to retrieve plugin info from the metadata URL.'; - } - exit; - } - } - -endif; diff --git a/vendor/yahnis-elsts/plugin-update-checker/Puc/v5/PucFactory.php b/vendor/yahnis-elsts/plugin-update-checker/Puc/v5/PucFactory.php new file mode 100644 index 000000000..3cda059d9 --- /dev/null +++ b/vendor/yahnis-elsts/plugin-update-checker/Puc/v5/PucFactory.php @@ -0,0 +1,10 @@ +rootDir = dirname(__FILE__) . '/'; + + $namespaceWithSlash = __NAMESPACE__ . '\\'; + $this->prefix = $namespaceWithSlash; + + $this->libraryDir = $this->rootDir . '../..'; + if ( !self::isPhar() ) { + $this->libraryDir = realpath($this->libraryDir); + } + $this->libraryDir = $this->libraryDir . '/'; + + //Usually, dependencies like Parsedown are in the global namespace, + //but if someone adds a custom namespace to the entire library, they + //will be in the same namespace as this class. + $isCustomNamespace = ( + substr($namespaceWithSlash, 0, strlen(self::DEFAULT_NS_PREFIX)) !== self::DEFAULT_NS_PREFIX + ); + $libraryPrefix = $isCustomNamespace ? $namespaceWithSlash : ''; + + $this->staticMap = array( + $libraryPrefix . 'PucReadmeParser' => 'vendor/PucReadmeParser.php', + $libraryPrefix . 'Parsedown' => 'vendor/Parsedown.php', + ); + + //Add the generic, major-version-only factory class to the static map. + $versionSeparatorPos = strrpos(__NAMESPACE__, '\\v'); + if ( $versionSeparatorPos !== false ) { + $versionSegment = substr(__NAMESPACE__, $versionSeparatorPos + 1); + $pointPos = strpos($versionSegment, 'p'); + if ( ($pointPos !== false) && ($pointPos > 1) ) { + $majorVersionSegment = substr($versionSegment, 0, $pointPos); + $majorVersionNs = __NAMESPACE__ . '\\' . $majorVersionSegment; + $this->staticMap[$majorVersionNs . '\\PucFactory'] = + 'Puc/' . $majorVersionSegment . '/Factory.php'; + } + } + + spl_autoload_register(array($this, 'autoload')); + } + + /** + * Determine if this file is running as part of a Phar archive. + * + * @return bool + */ + private static function isPhar() { + //Check if the current file path starts with "phar://". + static $pharProtocol = 'phar://'; + return (substr(__FILE__, 0, strlen($pharProtocol)) === $pharProtocol); + } + + public function autoload($className) { + if ( isset($this->staticMap[$className]) && file_exists($this->libraryDir . $this->staticMap[$className]) ) { + include($this->libraryDir . $this->staticMap[$className]); + return; + } + + if ( strpos($className, $this->prefix) === 0 ) { + $path = substr($className, strlen($this->prefix)); + $path = str_replace(array('_', '\\'), '/', $path); + $path = $this->rootDir . $path . '.php'; + + if ( file_exists($path) ) { + include $path; + } + } + } + } + +endif; diff --git a/vendor/yahnis-elsts/plugin-update-checker/Puc/v4p13/DebugBar/Extension.php b/vendor/yahnis-elsts/plugin-update-checker/Puc/v5p1/DebugBar/Extension.php similarity index 73% rename from vendor/yahnis-elsts/plugin-update-checker/Puc/v4p13/DebugBar/Extension.php rename to vendor/yahnis-elsts/plugin-update-checker/Puc/v5p1/DebugBar/Extension.php index 4619c0fba..01f43304c 100644 --- a/vendor/yahnis-elsts/plugin-update-checker/Puc/v4p13/DebugBar/Extension.php +++ b/vendor/yahnis-elsts/plugin-update-checker/Puc/v5p1/DebugBar/Extension.php @@ -1,12 +1,17 @@ updateChecker = $updateChecker; @@ -14,14 +19,14 @@ public function __construct($updateChecker, $panelClass = null) { $this->panelClass = $panelClass; } - if ( version_compare(PHP_VERSION, '5.3', '>=') && (strpos($this->panelClass, '\\') === false) ) { + if ( (strpos($this->panelClass, '\\') === false) ) { $this->panelClass = __NAMESPACE__ . '\\' . $this->panelClass; } add_filter('debug_bar_panels', array($this, 'addDebugBarPanel')); add_action('debug_bar_enqueue_scripts', array($this, 'enqueuePanelDependencies')); - add_action('wp_ajax_puc_v4_debug_check_now', array($this, 'ajaxCheckNow')); + add_action('wp_ajax_puc_v5_debug_check_now', array($this, 'ajaxCheckNow')); } /** @@ -42,17 +47,17 @@ public function addDebugBarPanel($panels) { */ public function enqueuePanelDependencies() { wp_enqueue_style( - 'puc-debug-bar-style-v4', + 'puc-debug-bar-style-v5', $this->getLibraryUrl("/css/puc-debug-bar.css"), array('debug-bar'), - '20171124' + '20221008' ); wp_enqueue_script( - 'puc-debug-bar-js-v4', + 'puc-debug-bar-js-v5', $this->getLibraryUrl("/js/debug-bar.js"), array('jquery'), - '20201209' + '20221008' ); } @@ -61,14 +66,16 @@ public function enqueuePanelDependencies() { * the update checking process works as expected. */ public function ajaxCheckNow() { - if ( $_POST['uid'] !== $this->updateChecker->getUniqueName('uid') ) { + //phpcs:ignore WordPress.Security.NonceVerification.Missing -- Nonce is checked in preAjaxRequest(). + if ( !isset($_POST['uid']) || ($_POST['uid'] !== $this->updateChecker->getUniqueName('uid')) ) { return; } $this->preAjaxRequest(); $update = $this->updateChecker->checkForUpdates(); if ( $update !== null ) { echo "An update is available:"; - echo '
', htmlentities(print_r($update, true)), '
'; + //phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_print_r -- For debugging output. + echo '
', esc_html(print_r($update, true)), '
'; } else { echo 'No updates found.'; } @@ -79,8 +86,8 @@ public function ajaxCheckNow() { foreach (array_values($errors) as $num => $item) { $wpError = $item['error']; - /** @var WP_Error $wpError */ - printf('

%d) %s

', $num + 1, esc_html($wpError->get_error_message())); + /** @var \WP_Error $wpError */ + printf('

%d) %s

', intval($num + 1), esc_html($wpError->get_error_message())); echo '
'; printf('
Error code:
%s
', esc_html($wpError->get_error_code())); @@ -92,7 +99,7 @@ public function ajaxCheckNow() { if ( isset($item['httpResponse']) ) { if ( is_wp_error($item['httpResponse']) ) { $httpError = $item['httpResponse']; - /** @var WP_Error $httpError */ + /** @var \WP_Error $httpError */ printf( '
WordPress HTTP API error:
%s (%s)
', esc_html($httpError->get_error_message()), @@ -102,8 +109,8 @@ public function ajaxCheckNow() { //Status code. printf( '
HTTP status:
%d %s
', - wp_remote_retrieve_response_code($item['httpResponse']), - wp_remote_retrieve_response_message($item['httpResponse']) + esc_html(wp_remote_retrieve_response_code($item['httpResponse'])), + esc_html(wp_remote_retrieve_response_message($item['httpResponse'])) ); //Headers. @@ -142,7 +149,9 @@ protected function preAjaxRequest() { } check_ajax_referer('puc-ajax'); + //phpcs:ignore WordPress.PHP.DiscouragedPHPFunctions.runtime_configuration_error_reporting -- Part of a debugging feature. error_reporting(E_ALL); + //phpcs:ignore WordPress.PHP.IniSet.display_errors_Blacklisted @ini_set('display_errors', 'On'); } @@ -152,7 +161,7 @@ protected function preAjaxRequest() { public function removeHooks() { remove_filter('debug_bar_panels', array($this, 'addDebugBarPanel')); remove_action('debug_bar_enqueue_scripts', array($this, 'enqueuePanelDependencies')); - remove_action('wp_ajax_puc_v4_debug_check_now', array($this, 'ajaxCheckNow')); + remove_action('wp_ajax_puc_v5_debug_check_now', array($this, 'ajaxCheckNow')); } /** @@ -163,11 +172,11 @@ private function getLibraryUrl($filePath) { $absolutePath = realpath(dirname(__FILE__) . '/../../../' . ltrim($filePath, '/')); //Where is the library located inside the WordPress directory structure? - $absolutePath = Puc_v4p13_Factory::normalizePath($absolutePath); + $absolutePath = PucFactory::normalizePath($absolutePath); - $pluginDir = Puc_v4p13_Factory::normalizePath(WP_PLUGIN_DIR); - $muPluginDir = Puc_v4p13_Factory::normalizePath(WPMU_PLUGIN_DIR); - $themeDir = Puc_v4p13_Factory::normalizePath(get_theme_root()); + $pluginDir = PucFactory::normalizePath(WP_PLUGIN_DIR); + $muPluginDir = PucFactory::normalizePath(WPMU_PLUGIN_DIR); + $themeDir = PucFactory::normalizePath(get_theme_root()); if ( (strpos($absolutePath, $pluginDir) === 0) || (strpos($absolutePath, $muPluginDir) === 0) ) { //It's part of a plugin. diff --git a/vendor/yahnis-elsts/plugin-update-checker/Puc/v4p13/DebugBar/Panel.php b/vendor/yahnis-elsts/plugin-update-checker/Puc/v5p1/DebugBar/Panel.php similarity index 85% rename from vendor/yahnis-elsts/plugin-update-checker/Puc/v4p13/DebugBar/Panel.php rename to vendor/yahnis-elsts/plugin-update-checker/Puc/v5p1/DebugBar/Panel.php index 6abcfa641..b880d650f 100644 --- a/vendor/yahnis-elsts/plugin-update-checker/Puc/v4p13/DebugBar/Panel.php +++ b/vendor/yahnis-elsts/plugin-update-checker/Puc/v5p1/DebugBar/Panel.php @@ -1,9 +1,12 @@ '; @@ -20,7 +23,7 @@ public function __construct($updateChecker) { public function render() { printf( - '
', + '
', esc_attr($this->updateChecker->getUniqueName('debug-bar-panel')), esc_attr($this->updateChecker->slug), esc_attr($this->updateChecker->getUniqueName('uid')), @@ -119,7 +122,10 @@ private function displayCurrentUpdate() { $fields = $this->getUpdateFields(); foreach($fields as $field) { if ( property_exists($update, $field) ) { - $this->row(ucwords(str_replace('_', ' ', $field)), htmlentities($update->$field)); + $this->row( + ucwords(str_replace('_', ' ', $field)), + isset($update->$field) ? htmlentities($update->$field) : null + ); } } echo ''; @@ -154,11 +160,18 @@ private function formatTimestamp($unixTime) { public function row($name, $value) { if ( is_object($value) || is_array($value) ) { + //This is specifically for debugging, so print_r() is fine. + //phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_print_r $value = '
' . htmlentities(print_r($value, true)) . '
'; } else if ($value === null) { $value = 'null'; } - printf('%1$s %2$s', $name, $value); + printf( + '%1$s %2$s', + esc_html($name), + //phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- Escaped above. + $value + ); } } diff --git a/vendor/yahnis-elsts/plugin-update-checker/Puc/v5p1/DebugBar/PluginExtension.php b/vendor/yahnis-elsts/plugin-update-checker/Puc/v5p1/DebugBar/PluginExtension.php new file mode 100644 index 000000000..21fbe0b5e --- /dev/null +++ b/vendor/yahnis-elsts/plugin-update-checker/Puc/v5p1/DebugBar/PluginExtension.php @@ -0,0 +1,40 @@ +updateChecker->getUniqueName('uid')) ) { + return; + } + $this->preAjaxRequest(); + $info = $this->updateChecker->requestInfo(); + if ( $info !== null ) { + echo 'Successfully retrieved plugin info from the metadata URL:'; + //phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_print_r -- For debugging output. + echo '
', esc_html(print_r($info, true)), '
'; + } else { + echo 'Failed to retrieve plugin info from the metadata URL.'; + } + exit; + } + } + +endif; diff --git a/vendor/yahnis-elsts/plugin-update-checker/Puc/v4p13/DebugBar/PluginPanel.php b/vendor/yahnis-elsts/plugin-update-checker/Puc/v5p1/DebugBar/PluginPanel.php similarity index 76% rename from vendor/yahnis-elsts/plugin-update-checker/Puc/v4p13/DebugBar/PluginPanel.php rename to vendor/yahnis-elsts/plugin-update-checker/Puc/v5p1/DebugBar/PluginPanel.php index d73caa6e8..d741e810e 100644 --- a/vendor/yahnis-elsts/plugin-update-checker/Puc/v4p13/DebugBar/PluginPanel.php +++ b/vendor/yahnis-elsts/plugin-update-checker/Puc/v5p1/DebugBar/PluginPanel.php @@ -1,10 +1,13 @@ validateMetadata($apiResponse); if ( is_wp_error($valid) ){ do_action('puc_api_error', $valid); - trigger_error($valid->get_error_message(), E_USER_NOTICE); + //phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_trigger_error -- For plugin developers. + trigger_error(esc_html($valid->get_error_message()), E_USER_NOTICE); return false; } @@ -53,10 +61,10 @@ protected static function createFromJson($json, $target) { /** * No validation by default! Subclasses should check that the required fields are present. * - * @param StdClass $apiResponse - * @return bool|WP_Error + * @param \StdClass $apiResponse + * @return bool|\WP_Error */ - protected function validateMetadata(/** @noinspection PhpUnusedParameterInspection */ $apiResponse) { + protected function validateMetadata($apiResponse) { return true; } @@ -64,10 +72,10 @@ protected function validateMetadata(/** @noinspection PhpUnusedParameterInspecti * Create a new instance by copying the necessary fields from another object. * * @abstract - * @param StdClass|self $object The source object. + * @param \StdClass|self $object The source object. * @return self The new copy. */ - public static function fromObject(/** @noinspection PhpUnusedParameterInspection */ $object) { + public static function fromObject($object) { throw new LogicException('The ' . __METHOD__ . ' method must be implemented by subclasses'); } @@ -77,7 +85,7 @@ public static function fromObject(/** @noinspection PhpUnusedParameterInspection * avoids the "incomplete object" problem if the cached value is loaded * before this class. * - * @return StdClass + * @return \StdClass */ public function toStdClass() { $object = new stdClass(); @@ -95,8 +103,8 @@ abstract public function toWpFormat(); /** * Copy known fields from one object to another. * - * @param StdClass|self $from - * @param StdClass|self $to + * @param \StdClass|self $from + * @param \StdClass|self $to */ protected function copyFields($from, $to) { $fields = $this->getFieldNames(); diff --git a/vendor/yahnis-elsts/plugin-update-checker/Puc/v4p13/OAuthSignature.php b/vendor/yahnis-elsts/plugin-update-checker/Puc/v5p1/OAuthSignature.php similarity index 87% rename from vendor/yahnis-elsts/plugin-update-checker/Puc/v4p13/OAuthSignature.php rename to vendor/yahnis-elsts/plugin-update-checker/Puc/v5p1/OAuthSignature.php index c04fa5ed5..578bc72c8 100644 --- a/vendor/yahnis-elsts/plugin-update-checker/Puc/v4p13/OAuthSignature.php +++ b/vendor/yahnis-elsts/plugin-update-checker/Puc/v5p1/OAuthSignature.php @@ -1,11 +1,12 @@ updateChecker->triggerError( sprintf( - "Can't to read the Version header for '%s'. The filename is incorrect or is not a plugin.", + "Cannot read the Version header for '%s'. The filename is incorrect or is not a plugin.", $this->updateChecker->pluginFile ), E_USER_WARNING @@ -140,7 +145,6 @@ public function getPluginHeader() { } if ( !function_exists('get_plugin_data') ) { - /** @noinspection PhpIncludeInspection */ require_once(ABSPATH . '/wp-admin/includes/plugin.php'); } return get_plugin_data($this->pluginAbsolutePath, false, false); @@ -170,8 +174,8 @@ public function isMuPlugin() { $pluginPath = realpath($this->pluginAbsolutePath); //If realpath() fails, just normalize the syntax instead. if (($muPluginDir === false) || ($pluginPath === false)) { - $muPluginDir = Puc_v4p13_Factory::normalizePath(WPMU_PLUGIN_DIR); - $pluginPath = Puc_v4p13_Factory::normalizePath($this->pluginAbsolutePath); + $muPluginDir = PucFactory::normalizePath(WPMU_PLUGIN_DIR); + $pluginPath = PucFactory::normalizePath($this->pluginAbsolutePath); } $cachedResult = (strpos($pluginPath, $muPluginDir) === 0); diff --git a/vendor/yahnis-elsts/plugin-update-checker/Puc/v4p13/Plugin/Info.php b/vendor/yahnis-elsts/plugin-update-checker/Puc/v5p1/Plugin/PluginInfo.php similarity index 91% rename from vendor/yahnis-elsts/plugin-update-checker/Puc/v4p13/Plugin/Info.php rename to vendor/yahnis-elsts/plugin-update-checker/Puc/v5p1/Plugin/PluginInfo.php index 40941e275..db8e51efa 100644 --- a/vendor/yahnis-elsts/plugin-update-checker/Puc/v4p13/Plugin/Info.php +++ b/vendor/yahnis-elsts/plugin-update-checker/Puc/v5p1/Plugin/PluginInfo.php @@ -1,5 +1,9 @@ name) || empty($apiResponse->version) ) { - return new WP_Error( + return new \WP_Error( 'puc-invalid-metadata', "The plugin metadata file does not contain the required 'name' and/or 'version' keys." ); @@ -88,7 +92,7 @@ protected function validateMetadata($apiResponse) { * @return object */ public function toWpFormat(){ - $info = new stdClass; + $info = new \stdClass; //The custom update API is built so that many fields have the same name and format //as those returned by the native WordPress.org API. These can be assigned directly. diff --git a/vendor/yahnis-elsts/plugin-update-checker/Puc/v4p13/Plugin/Ui.php b/vendor/yahnis-elsts/plugin-update-checker/Puc/v5p1/Plugin/Ui.php similarity index 89% rename from vendor/yahnis-elsts/plugin-update-checker/Puc/v4p13/Plugin/Ui.php rename to vendor/yahnis-elsts/plugin-update-checker/Puc/v5p1/Plugin/Ui.php index b3ea175a0..1b1fdf6ac 100644 --- a/vendor/yahnis-elsts/plugin-update-checker/Puc/v4p13/Plugin/Ui.php +++ b/vendor/yahnis-elsts/plugin-update-checker/Puc/v5p1/Plugin/Ui.php @@ -1,14 +1,16 @@ updateChecker = $updateChecker; @@ -172,7 +174,7 @@ public function handleManualCheck() { foreach ($lastRequestApiErrors as $item) { $wpError = $item['error']; - /** @var WP_Error $wpError */ + /** @var \WP_Error $wpError */ if ( !in_array($wpError->get_error_code(), $questionableErrorCodes) ) { $foundCriticalErrors = true; break; @@ -204,8 +206,9 @@ public function handleManualCheck() { * You can change the result message by using the "puc_manual_check_message-$slug" filter. */ public function displayManualCheckResult() { + //phpcs:disable WordPress.Security.NonceVerification.Recommended -- Just displaying a message. if ( isset($_GET['puc_update_check_result'], $_GET['puc_slug']) && ($_GET['puc_slug'] == $this->updateChecker->slug) ) { - $status = strval($_GET['puc_update_check_result']); + $status = sanitize_key($_GET['puc_update_check_result']); $title = $this->updateChecker->getInstalledPackage()->getPluginTitle(); $noticeClass = 'updated notice-success'; $details = ''; @@ -221,16 +224,29 @@ public function displayManualCheckResult() { $details = $this->formatManualCheckErrors(get_site_transient($this->manualCheckErrorTransient)); delete_site_transient($this->manualCheckErrorTransient); } else { - $message = sprintf(__('Unknown update checker status "%s"', 'plugin-update-checker'), htmlentities($status)); + $message = sprintf(__('Unknown update checker status "%s"', 'plugin-update-checker'), $status); $noticeClass = 'error notice-error'; } + + $message = esc_html($message); + + //Plugins can replace the message with their own, including adding HTML. + $message = apply_filters( + $this->updateChecker->getUniqueName('manual_check_message'), + $message, + $status + ); + printf( '

%s

%s
', - $noticeClass, - apply_filters($this->updateChecker->getUniqueName('manual_check_message'), $message, $status), + esc_attr($noticeClass), + //phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- Was escaped above, and plugins can add HTML. + $message, + //phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- Contains HTML. Content should already be escaped. $details ); } + //phpcs:enable } /** @@ -254,11 +270,11 @@ protected function formatManualCheckErrors($errors) { } foreach ($errors as $item) { $wpError = $item['error']; - /** @var WP_Error $wpError */ + /** @var \WP_Error $wpError */ $output .= sprintf( $formatString, - $wpError->get_error_message(), - $wpError->get_error_code() + esc_html($wpError->get_error_message()), + esc_html($wpError->get_error_code()) ); } if ( $showAsList ) { diff --git a/vendor/yahnis-elsts/plugin-update-checker/Puc/v4p13/Plugin/Update.php b/vendor/yahnis-elsts/plugin-update-checker/Puc/v5p1/Plugin/Update.php similarity index 85% rename from vendor/yahnis-elsts/plugin-update-checker/Puc/v4p13/Plugin/Update.php rename to vendor/yahnis-elsts/plugin-update-checker/Puc/v5p1/Plugin/Update.php index 9b3c5a031..475e4961c 100644 --- a/vendor/yahnis-elsts/plugin-update-checker/Puc/v4p13/Plugin/Update.php +++ b/vendor/yahnis-elsts/plugin-update-checker/Puc/v5p1/Plugin/Update.php @@ -1,5 +1,9 @@ triggerError(sprintf( 'Plugin slug "%s" is already in use by %s. Slugs must be unique.', - htmlentities($slug), - htmlentities($slugUsedBy) + $slug, + $slugUsedBy ), E_USER_ERROR); } add_filter($slugCheckFilter, array($this, 'getAbsolutePath')); @@ -68,17 +75,17 @@ public function __construct($metadataUrl, $pluginFile, $slug = '', $checkPeriod //Details: https://github.com/YahnisElsts/plugin-update-checker/issues/138#issuecomment-335590964 add_action('uninstall_' . $this->pluginFile, array($this, 'removeHooks')); - $this->extraUi = new Puc_v4p13_Plugin_Ui($this); + $this->extraUi = new Ui($this); } /** * Create an instance of the scheduler. * * @param int $checkPeriod - * @return Puc_v4p13_Scheduler + * @return Scheduler */ protected function createScheduler($checkPeriod) { - $scheduler = new Puc_v4p13_Scheduler($this, $checkPeriod, array('load-plugins.php')); + $scheduler = new Scheduler($this, $checkPeriod, array('load-plugins.php')); register_deactivation_hook($this->pluginFile, array($scheduler, 'removeUpdaterCron')); return $scheduler; } @@ -124,13 +131,17 @@ public function removeHooks() { * @uses wp_remote_get() * * @param array $queryArgs Additional query arguments to append to the request. Optional. - * @return Puc_v4p13_Plugin_Info + * @return PluginInfo */ public function requestInfo($queryArgs = array()) { - list($pluginInfo, $result) = $this->requestMetadata('Puc_v4p13_Plugin_Info', 'request_info', $queryArgs); + list($pluginInfo, $result) = $this->requestMetadata( + PluginInfo::class, + 'request_info', + $queryArgs + ); if ( $pluginInfo !== null ) { - /** @var Puc_v4p13_Plugin_Info $pluginInfo */ + /** @var PluginInfo $pluginInfo */ $pluginInfo->filename = $this->pluginFile; $pluginInfo->slug = $this->slug; } @@ -142,9 +153,9 @@ public function requestInfo($queryArgs = array()) { /** * Retrieve the latest update (if any) from the configured API endpoint. * - * @uses PluginUpdateChecker::requestInfo() + * @uses UpdateChecker::requestInfo() * - * @return Puc_v4p13_Update|null An instance of Plugin_Update, or NULL when no updates are available. + * @return Update|null An instance of Plugin Update, or NULL when no updates are available. */ public function requestUpdate() { //For the sake of simplicity, this function just calls requestInfo() @@ -153,7 +164,7 @@ public function requestUpdate() { if ( $pluginInfo === null ){ return null; } - $update = Puc_v4p13_Plugin_Update::fromPluginInfo($pluginInfo); + $update = Update::fromPluginInfo($pluginInfo); $update = $this->filterUpdateResult($update); @@ -197,9 +208,9 @@ protected function shouldShowUpdates() { } /** - * @param stdClass|null $updates - * @param stdClass $updateToAdd - * @return stdClass + * @param \stdClass|null $updates + * @param \stdClass $updateToAdd + * @return \stdClass */ protected function addUpdateToList($updates, $updateToAdd) { if ( $this->package->isMuPlugin() ) { @@ -211,8 +222,8 @@ protected function addUpdateToList($updates, $updateToAdd) { } /** - * @param stdClass|null $updates - * @return stdClass|null + * @param \stdClass|null $updates + * @return \stdClass|null */ protected function removeUpdateFromList($updates) { $updates = parent::removeUpdateFromList($updates); @@ -246,7 +257,7 @@ protected function getNoUpdateItemFields() { 'banners' => array(), 'banners_rtl' => array(), 'tested' => '', - 'compatibility' => new stdClass(), + 'compatibility' => new \stdClass(), ) ); } @@ -255,7 +266,7 @@ protected function getNoUpdateItemFields() { * Alias for isBeingUpgraded(). * * @deprecated - * @param WP_Upgrader|null $upgrader The upgrader that's performing the current update. + * @param \WP_Upgrader|null $upgrader The upgrader that's performing the current update. * @return bool */ public function isPluginBeingUpgraded($upgrader = null) { @@ -265,7 +276,7 @@ public function isPluginBeingUpgraded($upgrader = null) { /** * Is there an update being installed for this plugin, right now? * - * @param WP_Upgrader|null $upgrader + * @param \WP_Upgrader|null $upgrader * @return bool */ public function isBeingUpgraded($upgrader = null) { @@ -281,12 +292,12 @@ public function isBeingUpgraded($upgrader = null) { * Uses cached update data. To retrieve update information straight from * the metadata URL, call requestUpdate() instead. * - * @return Puc_v4p13_Plugin_Update|null + * @return Update|null */ public function getUpdate() { $update = parent::getUpdate(); if ( isset($update) ) { - /** @var Puc_v4p13_Plugin_Update $update */ + /** @var Update $update */ $update->filename = $this->pluginFile; } return $update; @@ -391,20 +402,20 @@ public function addResultFilter($callback) { } protected function createDebugBarExtension() { - return new Puc_v4p13_DebugBar_PluginExtension($this); + return new DebugBar\PluginExtension($this); } /** * Create a package instance that represents this plugin or theme. * - * @return Puc_v4p13_InstalledPackage + * @return InstalledPackage */ protected function createInstalledPackage() { - return new Puc_v4p13_Plugin_Package($this->pluginAbsolutePath, $this); + return new Package($this->pluginAbsolutePath, $this); } /** - * @return Puc_v4p13_Plugin_Package + * @return Package */ public function getInstalledPackage() { return $this->package; diff --git a/vendor/yahnis-elsts/plugin-update-checker/Puc/v4p13/Factory.php b/vendor/yahnis-elsts/plugin-update-checker/Puc/v5p1/PucFactory.php similarity index 85% rename from vendor/yahnis-elsts/plugin-update-checker/Puc/v4p13/Factory.php rename to vendor/yahnis-elsts/plugin-update-checker/Puc/v5p1/PucFactory.php index f18b38979..e9cc69155 100644 --- a/vendor/yahnis-elsts/plugin-update-checker/Puc/v4p13/Factory.php +++ b/vendor/yahnis-elsts/plugin-update-checker/Puc/v5p1/PucFactory.php @@ -1,5 +1,12 @@ =') ) { - $checkerClass = __NAMESPACE__ . '\\' . $checkerClass; } if ( !isset($apiClass) ) { @@ -123,16 +124,12 @@ public static function buildUpdateChecker($metadataUrl, $fullPath, $slug = '', $ //VCS checker + an API client. $apiClass = self::getCompatibleClassVersion($apiClass); if ( $apiClass === null ) { - trigger_error(sprintf( + //phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_trigger_error + trigger_error(esc_html(sprintf( 'PUC %s does not support %s', - htmlentities(self::$latestCompatibleVersion), - htmlentities($service) - ), E_USER_ERROR); - return null; - } - - if ( version_compare(PHP_VERSION, '5.3', '>=') && (strpos($apiClass, '\\') === false) ) { - $apiClass = __NAMESPACE__ . '\\' . $apiClass; + self::$latestCompatibleVersion, + $service + )), E_USER_ERROR); } return new $checkerClass( @@ -150,7 +147,7 @@ public static function buildUpdateChecker($metadataUrl, $fullPath, $slug = '', $ * * Normalize a filesystem path. Introduced in WP 3.9. * Copying here allows use of the class on earlier versions. - * This version adapted from WP 4.8.2 (unchanged since 4.5.0) + * This version adapted from WP 4.8.2 (unchanged since 4.5.1) * * @param string $path Path to normalize. * @return string Normalized path. @@ -241,7 +238,7 @@ private static function getServiceURI($fullPath) { } //URI was not found so throw an error. - throw new RuntimeException( + throw new \RuntimeException( sprintf('Unable to locate URI in header of "%s"', htmlentities($fullPath)) ); } @@ -256,8 +253,8 @@ private static function getVcsService($metadataUrl) { $service = null; //Which hosting service does the URL point to? - $host = parse_url($metadataUrl, PHP_URL_HOST); - $path = parse_url($metadataUrl, PHP_URL_PATH); + $host = (string)(wp_parse_url($metadataUrl, PHP_URL_HOST)); + $path = (string)(wp_parse_url($metadataUrl, PHP_URL_PATH)); //Check if the path looks like "/user-name/repository". //For GitLab.com it can also be "/user/group1/group2/.../repository". @@ -337,12 +334,8 @@ protected static function compareVersions($a, $b) { */ public static function addVersion($generalClass, $versionedClass, $version) { if ( empty(self::$myMajorVersion) ) { - $className = (version_compare(PHP_VERSION, '5.3', '>=') && __NAMESPACE__) - ? substr(__CLASS__, strlen(__NAMESPACE__) + 1) - : __CLASS__; - - $nameParts = explode('_', $className, 3); - self::$myMajorVersion = substr(ltrim($nameParts[1], 'v'), 0, 1); + $lastNamespaceSegment = substr(__NAMESPACE__, strrpos(__NAMESPACE__, '\\') + 1); + self::$myMajorVersion = substr(ltrim($lastNamespaceSegment, 'v'), 0, 1); } //Store the greatest version number that matches our major version. diff --git a/vendor/yahnis-elsts/plugin-update-checker/Puc/v4p13/Scheduler.php b/vendor/yahnis-elsts/plugin-update-checker/Puc/v5p1/Scheduler.php similarity index 89% rename from vendor/yahnis-elsts/plugin-update-checker/Puc/v4p13/Scheduler.php rename to vendor/yahnis-elsts/plugin-update-checker/Puc/v5p1/Scheduler.php index cca04d7b5..b0a9707ba 100644 --- a/vendor/yahnis-elsts/plugin-update-checker/Puc/v4p13/Scheduler.php +++ b/vendor/yahnis-elsts/plugin-update-checker/Puc/v5p1/Scheduler.php @@ -1,11 +1,13 @@ checkPeriod . 'hours'; + //phpcs:ignore WordPress.WP.CronInterval.ChangeDetected -- WPCS fails to parse the callback. add_filter('cron_schedules', array($this, '_addCustomSchedule')); } if ( !wp_next_scheduled($this->cronHook) && !defined('WP_INSTALLING') ) { //Randomly offset the schedule to help prevent update server traffic spikes. Without this //most checks may happen during times of day when people are most likely to install new plugins. - $firstCheckTime = time() - rand(0, max($this->checkPeriod * 3600 - 15 * 60, 1)); + $upperLimit = max($this->checkPeriod * 3600 - 15 * 60, 1); + if ( function_exists('wp_rand') ) { + $randomOffset = wp_rand(0, $upperLimit); + } else { + //This constructor may be called before wp_rand() is available. + //phpcs:ignore WordPress.WP.AlternativeFunctions.rand_rand + $randomOffset = rand(0, $upperLimit); + } + $firstCheckTime = time() - $randomOffset; $firstCheckTime = apply_filters( $this->updateChecker->getUniqueName('first_check_time'), $firstCheckTime @@ -69,6 +80,7 @@ public function __construct($updateChecker, $checkPeriod, $hourlyHooks = array(' //Like WordPress itself, we check more often on certain pages. /** @see wp_update_plugins */ add_action('load-update-core.php', array($this, 'maybeCheckForUpdates')); + //phpcs:ignore Squiz.PHP.CommentedOutCode.Found -- Not actually code, just file names. //"load-update.php" and "load-plugins.php" or "load-themes.php". $this->hourlyCheckHooks = array_merge($this->hourlyCheckHooks, $hourlyHooks); foreach($this->hourlyCheckHooks as $hook) { @@ -89,7 +101,7 @@ public function __construct($updateChecker, $checkPeriod, $hourlyHooks = array(' * We look at the parameters to decide whether to call maybeCheckForUpdates() or not. * We also check if the update checker has been removed by the update. * - * @param WP_Upgrader $upgrader WP_Upgrader instance + * @param \WP_Upgrader $upgrader WP_Upgrader instance * @param array $upgradeInfo extra information about the upgrade */ public function upgraderProcessComplete( @@ -116,7 +128,7 @@ public function upgraderProcessComplete( //Filter out notifications of upgrades that should have no bearing upon whether or not our //current info is up-to-date. - if ( is_a($this->updateChecker, 'Puc_v4p13_Theme_UpdateChecker') ) { + if ( is_a($this->updateChecker, Theme\UpdateChecker::class) ) { if ( 'theme' !== $upgradeInfo['type'] || !isset($upgradeInfo['themes']) ) { return; } @@ -130,7 +142,7 @@ public function upgraderProcessComplete( } } - if ( is_a($this->updateChecker, 'Puc_v4p13_Plugin_UpdateChecker') ) { + if ( is_a($this->updateChecker, Plugin\UpdateChecker::class) ) { if ( 'plugin' !== $upgradeInfo['type'] || !isset($upgradeInfo['plugins']) ) { return; } diff --git a/vendor/yahnis-elsts/plugin-update-checker/Puc/v4p13/StateStore.php b/vendor/yahnis-elsts/plugin-update-checker/Puc/v5p1/StateStore.php similarity index 78% rename from vendor/yahnis-elsts/plugin-update-checker/Puc/v4p13/StateStore.php rename to vendor/yahnis-elsts/plugin-update-checker/Puc/v5p1/StateStore.php index 8eb381dbd..b6f6cc103 100644 --- a/vendor/yahnis-elsts/plugin-update-checker/Puc/v4p13/StateStore.php +++ b/vendor/yahnis-elsts/plugin-update-checker/Puc/v5p1/StateStore.php @@ -1,8 +1,9 @@ lazyLoad(); @@ -73,10 +74,10 @@ public function getUpdate() { } /** - * @param Puc_v4p13_Update|null $update + * @param Update|null $update * @return $this */ - public function setUpdate(Puc_v4p13_Update $update = null) { + public function setUpdate(Update $update = null) { $this->lazyLoad(); $this->update = $update; return $this; @@ -127,7 +128,7 @@ public function setTranslations($translationUpdates) { } public function save() { - $state = new stdClass(); + $state = new \stdClass(); $state->lastCheck = $this->lastCheck; $state->checkedVersion = $this->checkedVersion; @@ -138,7 +139,7 @@ public function save() { $updateClass = get_class($this->update); $state->updateClass = $updateClass; $prefix = $this->getLibPrefix(); - if ( Puc_v4p13_Utils::startsWith($updateClass, $prefix) ) { + if ( Utils::startsWith($updateClass, $prefix) ) { $state->updateBaseClass = substr($updateClass, strlen($prefix)); } } @@ -169,8 +170,8 @@ protected function load() { return; } - $this->lastCheck = intval(Puc_v4p13_Utils::get($state, 'lastCheck', 0)); - $this->checkedVersion = Puc_v4p13_Utils::get($state, 'checkedVersion', ''); + $this->lastCheck = intval(Utils::get($state, 'lastCheck', 0)); + $this->checkedVersion = Utils::get($state, 'checkedVersion', ''); $this->update = null; if ( isset($state->update) ) { @@ -184,8 +185,9 @@ protected function load() { $updateClass = $state->updateClass; } - if ( ($updateClass !== null) && class_exists($updateClass) ) { - $this->update = call_user_func(array($updateClass, 'fromObject'), $state->update); + $factory = array($updateClass, 'fromObject'); + if ( ($updateClass !== null) && is_callable($factory) ) { + $this->update = call_user_func($factory, $state->update); } } } @@ -199,17 +201,8 @@ public function delete() { } private function getLibPrefix() { - $lastSlashPos = strrpos(__CLASS__, '\\'); - if ( $lastSlashPos !== false ) { - $namespacePrefix = substr(__CLASS__, 0, $lastSlashPos + 1); - $className = substr(__CLASS__, $lastSlashPos + 1); - } else { - $namespacePrefix = ''; - $className = __CLASS__; - } - - $parts = explode('_', $className, 3); - return $namespacePrefix . $parts[0] . '_' . $parts[1] . '_'; + //This assumes that the current class is at the top of the versioned namespace. + return __NAMESPACE__ . '\\'; } } diff --git a/vendor/yahnis-elsts/plugin-update-checker/Puc/v4p13/Theme/Package.php b/vendor/yahnis-elsts/plugin-update-checker/Puc/v5p1/Theme/Package.php similarity index 87% rename from vendor/yahnis-elsts/plugin-update-checker/Puc/v4p13/Theme/Package.php rename to vendor/yahnis-elsts/plugin-update-checker/Puc/v5p1/Theme/Package.php index f38cbfda9..030046ba6 100644 --- a/vendor/yahnis-elsts/plugin-update-checker/Puc/v4p13/Theme/Package.php +++ b/vendor/yahnis-elsts/plugin-update-checker/Puc/v5p1/Theme/Package.php @@ -1,14 +1,18 @@ $key) || empty($apiResponse->$key) ) { - return new WP_Error( + return new \WP_Error( 'tuc-invalid-metadata', sprintf('The theme metadata is missing the required "%s" key.', $key) ); diff --git a/vendor/yahnis-elsts/plugin-update-checker/Puc/v4p13/Theme/UpdateChecker.php b/vendor/yahnis-elsts/plugin-update-checker/Puc/v5p1/Theme/UpdateChecker.php similarity index 79% rename from vendor/yahnis-elsts/plugin-update-checker/Puc/v4p13/Theme/UpdateChecker.php rename to vendor/yahnis-elsts/plugin-update-checker/Puc/v5p1/Theme/UpdateChecker.php index c7de804af..85ca5fbe6 100644 --- a/vendor/yahnis-elsts/plugin-update-checker/Puc/v4p13/Theme/UpdateChecker.php +++ b/vendor/yahnis-elsts/plugin-update-checker/Puc/v5p1/Theme/UpdateChecker.php @@ -1,8 +1,15 @@ requestMetadata('Puc_v4p13_Theme_Update', 'request_update'); + list($themeUpdate, $result) = $this->requestMetadata(Update::class, 'request_update'); if ( $themeUpdate !== null ) { - /** @var Puc_v4p13_Theme_Update $themeUpdate */ + /** @var Update $themeUpdate */ $themeUpdate->slug = $this->slug; } @@ -71,16 +78,16 @@ public function userCanInstallUpdates() { * Create an instance of the scheduler. * * @param int $checkPeriod - * @return Puc_v4p13_Scheduler + * @return Scheduler */ protected function createScheduler($checkPeriod) { - return new Puc_v4p13_Scheduler($this, $checkPeriod, array('load-themes.php')); + return new Scheduler($this, $checkPeriod, array('load-themes.php')); } /** * Is there an update being installed right now for this theme? * - * @param WP_Upgrader|null $upgrader The upgrader that's performing the current update. + * @param \WP_Upgrader|null $upgrader The upgrader that's performing the current update. * @return bool */ public function isBeingUpgraded($upgrader = null) { @@ -88,7 +95,7 @@ public function isBeingUpgraded($upgrader = null) { } protected function createDebugBarExtension() { - return new Puc_v4p13_DebugBar_Extension($this, 'Puc_v4p13_DebugBar_ThemePanel'); + return new DebugBar\Extension($this, DebugBar\ThemePanel::class); } /** @@ -142,10 +149,10 @@ public function addResultFilter($callback) { /** * Create a package instance that represents this plugin or theme. * - * @return Puc_v4p13_InstalledPackage + * @return InstalledPackage */ protected function createInstalledPackage() { - return new Puc_v4p13_Theme_Package($this->stylesheet, $this); + return new Package($this->stylesheet, $this); } } diff --git a/vendor/yahnis-elsts/plugin-update-checker/Puc/v4p13/Update.php b/vendor/yahnis-elsts/plugin-update-checker/Puc/v5p1/Update.php similarity index 79% rename from vendor/yahnis-elsts/plugin-update-checker/Puc/v4p13/Update.php rename to vendor/yahnis-elsts/plugin-update-checker/Puc/v5p1/Update.php index 62a573925..f43d1ff8f 100644 --- a/vendor/yahnis-elsts/plugin-update-checker/Puc/v4p13/Update.php +++ b/vendor/yahnis-elsts/plugin-update-checker/Puc/v5p1/Update.php @@ -1,5 +1,9 @@ package = $this->createInstalledPackage(); $this->scheduler = $this->createScheduler($checkPeriod); - $this->upgraderStatus = new Puc_v4p13_UpgraderStatus(); - $this->updateState = new Puc_v4p13_StateStore($this->optionName); + $this->upgraderStatus = new UpgraderStatus(); + $this->updateState = new StateStore($this->optionName); if ( did_action('init') ) { $this->loadTextDomain(); @@ -206,7 +210,7 @@ abstract public function userCanInstallUpdates(); */ public function allowMetadataHost($allow, $host) { if ( $this->cachedMetadataHost === 0 ) { - $this->cachedMetadataHost = parse_url($this->metadataUrl, PHP_URL_HOST); + $this->cachedMetadataHost = wp_parse_url($this->metadataUrl, PHP_URL_HOST); } if ( is_string($this->cachedMetadataHost) && (strtolower($host) === strtolower($this->cachedMetadataHost)) ) { @@ -218,12 +222,12 @@ public function allowMetadataHost($allow, $host) { /** * Create a package instance that represents this plugin or theme. * - * @return Puc_v4p13_InstalledPackage + * @return InstalledPackage */ abstract protected function createInstalledPackage(); /** - * @return Puc_v4p13_InstalledPackage + * @return InstalledPackage */ public function getInstalledPackage() { return $this->package; @@ -236,14 +240,14 @@ public function getInstalledPackage() { * and substitute their own scheduler. * * @param int $checkPeriod - * @return Puc_v4p13_Scheduler + * @return Scheduler */ abstract protected function createScheduler($checkPeriod); /** * Check for updates. The results are stored in the DB option specified in $optionName. * - * @return Puc_v4p13_Update|null + * @return Update|null */ public function checkForUpdates() { $installedVersion = $this->getInstalledVersion(); @@ -277,7 +281,7 @@ public function checkForUpdates() { /** * Load the update checker state from the DB. * - * @return Puc_v4p13_StateStore + * @return StateStore */ public function getUpdateState() { return $this->updateState->lazyLoad(); @@ -302,7 +306,7 @@ public function resetUpdateState() { * Uses cached update data. To retrieve update information straight from * the metadata URL, call requestUpdate() instead. * - * @return Puc_v4p13_Update|null + * @return Update|null */ public function getUpdate() { $update = $this->updateState->getUpdate(); @@ -323,16 +327,17 @@ public function getUpdate() { * * Subclasses should run the update through filterUpdateResult before returning it. * - * @return Puc_v4p13_Update An instance of Update, or NULL when no updates are available. + * @return Update An instance of Update, or NULL when no updates are available. */ abstract public function requestUpdate(); /** * Filter the result of a requestUpdate() call. * - * @param Puc_v4p13_Update|null $update + * @template T of Update + * @param T|null $update * @param array|WP_Error|null $httpResult The value returned by wp_remote_get(), if any. - * @return Puc_v4p13_Update + * @return T */ protected function filterUpdateResult($update, $httpResult = null) { //Let plugins/themes modify the update. @@ -355,9 +360,9 @@ protected function filterUpdateResult($update, $httpResult = null) { * "Compatibility: Unknown". * The function mimics how wordpress.org API crafts the "tested" field out of "Tested up to". * - * @param Puc_v4p13_Metadata|null $update + * @param Metadata|null $update */ - protected function fixSupportedWordpressVersion(Puc_v4p13_Metadata $update = null) { + protected function fixSupportedWordpressVersion(Metadata $update = null) { if ( !isset($update->tested) || !preg_match('/^\d++\.\d++$/', $update->tested) ) { return; } @@ -427,7 +432,8 @@ public function getAbsoluteDirectoryPath() { */ public function triggerError($message, $errorType) { if ( $this->isDebugModeEnabled() ) { - trigger_error($message, $errorType); + //phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_trigger_error -- Only happens in debug mode. + trigger_error(esc_html($message), $errorType); } } @@ -462,7 +468,7 @@ public function getUniqueName($baseTag) { * Store API errors that are generated when checking for updates. * * @internal - * @param WP_Error $error + * @param \WP_Error $error * @param array|null $httpResponse * @param string|null $url * @param string|null $slug @@ -515,8 +521,8 @@ public function addFilter($tag, $callback, $priority = 10, $acceptedArgs = 1) { /** * Insert the latest update (if any) into the update list maintained by WP. * - * @param stdClass $updates Update list. - * @return stdClass Modified update list. + * @param \stdClass $updates Update list. + * @return \stdClass Modified update list. */ public function injectUpdate($updates) { //Is there an update to insert? @@ -543,9 +549,9 @@ public function injectUpdate($updates) { } /** - * @param stdClass|null $updates - * @param stdClass|array $updateToAdd - * @return stdClass + * @param \stdClass|null $updates + * @param \stdClass|array $updateToAdd + * @return \stdClass */ protected function addUpdateToList($updates, $updateToAdd) { if ( !is_object($updates) ) { @@ -558,8 +564,8 @@ protected function addUpdateToList($updates, $updateToAdd) { } /** - * @param stdClass|null $updates - * @return stdClass|null + * @param \stdClass|null $updates + * @return \stdClass|null */ protected function removeUpdateFromList($updates) { if ( isset($updates, $updates->response) ) { @@ -572,8 +578,8 @@ protected function removeUpdateFromList($updates) { * See this post for more information: * @link https://make.wordpress.org/core/2020/07/30/recommended-usage-of-the-updates-api-to-support-the-auto-updates-ui-for-plugins-and-themes-in-wordpress-5-5/ * - * @param stdClass|null $updates - * @return stdClass + * @param \stdClass|null $updates + * @return \stdClass */ protected function addNoUpdateItem($updates) { if ( !is_object($updates) ) { @@ -635,10 +641,10 @@ protected function shouldShowUpdates() { /** * Retrieve plugin or theme metadata from the JSON document at $this->metadataUrl. * - * @param string $metaClass Parse the JSON as an instance of this class. It must have a static fromJson method. + * @param class-string $metaClass Parse the JSON as an instance of this class. It must have a static fromJson method. * @param string $filterRoot * @param array $queryArgs Additional query arguments. - * @return array [Puc_v4p13_Metadata|null, array|WP_Error] A metadata instance and the value returned by wp_remote_get(). + * @return array A metadata instance and the value returned by wp_remote_get(). */ protected function requestMetadata($metaClass, $filterRoot, $queryArgs = array()) { //Query args to append to the URL. Plugins can add their own by using a filter callback (see addQueryArgFilter()). @@ -654,7 +660,7 @@ protected function requestMetadata($metaClass, $filterRoot, $queryArgs = array() //Various options for the wp_remote_get() call. Plugins can filter these, too. $options = array( - 'timeout' => 10, //seconds + 'timeout' => wp_doing_cron() ? 10 : 3, 'headers' => array( 'Accept' => 'application/json', ), @@ -675,7 +681,7 @@ protected function requestMetadata($metaClass, $filterRoot, $queryArgs = array() $status = $this->validateApiResponse($result); $metadata = null; if ( !is_wp_error($status) ){ - if ( version_compare(PHP_VERSION, '5.3', '>=') && (strpos($metaClass, '\\') === false) ) { + if ( (strpos($metaClass, '\\') === false) ) { $metaClass = __NAMESPACE__ . '\\' . $metaClass; } $metadata = call_user_func(array($metaClass, 'fromJson'), $result['body']); @@ -879,12 +885,12 @@ protected function isNotMyTranslation($translation) { * * @param string $source The directory to copy to /wp-content/plugins or /wp-content/themes. Usually a subdirectory of $remoteSource. * @param string $remoteSource WordPress has extracted the update to this directory. - * @param WP_Upgrader $upgrader + * @param \WP_Upgrader $upgrader * @return string|WP_Error */ public function fixDirectoryName($source, $remoteSource, $upgrader) { global $wp_filesystem; - /** @var WP_Filesystem_Base $wp_filesystem */ + /** @var \WP_Filesystem_Base $wp_filesystem */ //Basic sanity checks. if ( !isset($source, $remoteSource, $upgrader, $upgrader->skin, $wp_filesystem) ) { @@ -914,7 +920,7 @@ public function fixDirectoryName($source, $remoteSource, $upgrader) { ); } - /** @var WP_Upgrader_Skin $upgrader ->skin */ + /** @var \WP_Upgrader_Skin $upgrader ->skin */ $upgrader->skin->feedback(sprintf( 'Renaming %s to %s…', '' . basename($source) . '', @@ -938,7 +944,7 @@ public function fixDirectoryName($source, $remoteSource, $upgrader) { /** * Is there an update being installed right now, for this plugin or theme? * - * @param WP_Upgrader|null $upgrader The upgrader that's performing the current update. + * @param \WP_Upgrader|null $upgrader The upgrader that's performing the current update. * @return bool */ abstract public function isBeingUpgraded($upgrader = null); @@ -952,7 +958,7 @@ abstract public function isBeingUpgraded($upgrader = null); */ protected function isBadDirectoryStructure($remoteSource) { global $wp_filesystem; - /** @var WP_Filesystem_Base $wp_filesystem */ + /** @var \WP_Filesystem_Base $wp_filesystem */ $sourceFiles = $wp_filesystem->dirlist($remoteSource); if ( is_array($sourceFiles) ) { @@ -980,13 +986,13 @@ public function maybeInitDebugBar() { } protected function createDebugBarExtension() { - return new Puc_v4p13_DebugBar_Extension($this); + return new DebugBar\Extension($this); } /** * Display additional configuration details in the Debug Bar panel. * - * @param Puc_v4p13_DebugBar_Panel $panel + * @param DebugBar\Panel $panel */ public function onDisplayConfiguration($panel) { //Do nothing. Subclasses can use this to add additional info to the panel. diff --git a/vendor/yahnis-elsts/plugin-update-checker/Puc/v4p13/UpgraderStatus.php b/vendor/yahnis-elsts/plugin-update-checker/Puc/v5p1/UpgraderStatus.php similarity index 91% rename from vendor/yahnis-elsts/plugin-update-checker/Puc/v4p13/UpgraderStatus.php rename to vendor/yahnis-elsts/plugin-update-checker/Puc/v5p1/UpgraderStatus.php index 9f1232201..2dc67364f 100644 --- a/vendor/yahnis-elsts/plugin-update-checker/Puc/v4p13/UpgraderStatus.php +++ b/vendor/yahnis-elsts/plugin-update-checker/Puc/v5p1/UpgraderStatus.php @@ -1,5 +1,7 @@ skin; - if ( isset($skin->theme_info) && ($skin->theme_info instanceof WP_Theme) ) { + if ( isset($skin->theme_info) && ($skin->theme_info instanceof \WP_Theme) ) { $themeDirectoryName = $skin->theme_info->get_stylesheet(); - } elseif ( $skin instanceof Plugin_Upgrader_Skin ) { + } elseif ( $skin instanceof \Plugin_Upgrader_Skin ) { if ( isset($skin->plugin) && is_string($skin->plugin) && ($skin->plugin !== '') ) { $pluginFile = $skin->plugin; } - } elseif ( $skin instanceof Theme_Upgrader_Skin ) { + } elseif ( $skin instanceof \Theme_Upgrader_Skin ) { if ( isset($skin->theme) && is_string($skin->theme) && ($skin->theme !== '') ) { $themeDirectoryName = $skin->theme; } @@ -122,7 +124,6 @@ private function getThingBeingUpgradedBy($upgrader) { */ private function identifyPluginByHeaders($searchHeaders) { if ( !function_exists('get_plugins') ){ - /** @noinspection PhpIncludeInspection */ require_once( ABSPATH . '/wp-admin/includes/plugin.php' ); } diff --git a/vendor/yahnis-elsts/plugin-update-checker/Puc/v4p13/Utils.php b/vendor/yahnis-elsts/plugin-update-checker/Puc/v5p1/Utils.php similarity index 94% rename from vendor/yahnis-elsts/plugin-update-checker/Puc/v4p13/Utils.php rename to vendor/yahnis-elsts/plugin-update-checker/Puc/v5p1/Utils.php index f792ab77c..b664e1a2e 100644 --- a/vendor/yahnis-elsts/plugin-update-checker/Puc/v4p13/Utils.php +++ b/vendor/yahnis-elsts/plugin-update-checker/Puc/v5p1/Utils.php @@ -1,8 +1,9 @@ getUpdateDetectionStrategies($configBranch); + + if ( !empty($this->strategyFilterName) ) { + $strategies = apply_filters( + $this->strategyFilterName, + $strategies, + $this->slug + ); + } + + foreach ($strategies as $strategy) { + $reference = call_user_func($strategy); + if ( !empty($reference) ) { + return $reference; + } + } + return null; + } + + /** + * Get an ordered list of strategies that can be used to find the latest version. + * + * The update checker will try each strategy in order until one of them + * returns a valid reference. + * + * @param string $configBranch + * @return array Array of callables that return Vcs_Reference objects. + */ + abstract protected function getUpdateDetectionStrategies($configBranch); /** * Get the readme.txt file from the remote repository and parse it @@ -105,7 +176,7 @@ public function getLocalReadmeName() { * Get a branch. * * @param string $branchName - * @return Puc_v4p13_Vcs_Reference|null + * @return Reference|null */ abstract public function getBranch($branchName); @@ -113,7 +184,7 @@ abstract public function getBranch($branchName); * Get a specific tag. * * @param string $tagName - * @return Puc_v4p13_Vcs_Reference|null + * @return Reference|null */ abstract public function getTag($tagName); @@ -121,7 +192,7 @@ abstract public function getTag($tagName); * Get the tag that looks like the highest version number. * (Implementations should skip pre-release versions if possible.) * - * @return Puc_v4p13_Vcs_Reference|null + * @return Reference|null */ abstract public function getLatestTag(); @@ -147,7 +218,7 @@ protected function looksLikeVersion($name) { /** * Check if a tag appears to be named like a version number. * - * @param stdClass $tag + * @param \stdClass $tag * @return bool */ protected function isVersionTag($tag) { @@ -159,8 +230,8 @@ protected function isVersionTag($tag) { * Sort a list of tags as if they were version numbers. * Tags that don't look like version number will be removed. * - * @param stdClass[] $tags Array of tag objects. - * @return stdClass[] Filtered array of tags sorted in descending order. + * @param \stdClass[] $tags Array of tag objects. + * @return \stdClass[] Filtered array of tags sorted in descending order. */ protected function sortTagsByVersion($tags) { //Keep only those tags that look like version numbers. @@ -174,8 +245,8 @@ protected function sortTagsByVersion($tags) { /** * Compare two tags as if they were version number. * - * @param stdClass $tag1 Tag object. - * @param stdClass $tag2 Another tag object. + * @param \stdClass $tag1 Tag object. + * @param \stdClass $tag2 Another tag object. * @return int */ protected function compareTagNames($tag1, $tag2) { @@ -224,7 +295,6 @@ public function getRemoteChangelog($ref, $localDirectory) { return null; } - /** @noinspection PhpUndefinedClassInspection */ return Parsedown::instance()->text($changelog); } @@ -280,6 +350,13 @@ public function setHttpFilterName($filterName) { $this->httpFilterName = $filterName; } + /** + * @param string $filterName + */ + public function setStrategyFilterName($filterName) { + $this->strategyFilterName = $filterName; + } + /** * @param string $directory */ diff --git a/vendor/yahnis-elsts/plugin-update-checker/Puc/v4p13/Vcs/BaseChecker.php b/vendor/yahnis-elsts/plugin-update-checker/Puc/v5p1/Vcs/BaseChecker.php similarity index 72% rename from vendor/yahnis-elsts/plugin-update-checker/Puc/v4p13/Vcs/BaseChecker.php rename to vendor/yahnis-elsts/plugin-update-checker/Puc/v5p1/Vcs/BaseChecker.php index f83a43338..74c121503 100644 --- a/vendor/yahnis-elsts/plugin-update-checker/Puc/v4p13/Vcs/BaseChecker.php +++ b/vendor/yahnis-elsts/plugin-update-checker/Puc/v5p1/Vcs/BaseChecker.php @@ -1,7 +1,9 @@ [^/]+?)/(?P[^/#?&]+?)/?$@', $path, $matches) ) { $this->username = $matches['username']; $this->repository = $matches['repository']; } else { - throw new InvalidArgumentException('Invalid BitBucket repository URL: "' . $repositoryUrl . '"'); + throw new \InvalidArgumentException('Invalid BitBucket repository URL: "' . $repositoryUrl . '"'); } parent::__construct($repositoryUrl, $credentials); } - /** - * Figure out which reference (i.e tag or branch) contains the latest version. - * - * @param string $configBranch Start looking in this branch. - * @return null|Puc_v4p13_Vcs_Reference - */ - public function chooseReference($configBranch) { - $updateSource = null; - - //Check if there's a "Stable tag: 1.2.3" header that points to a valid tag. - $updateSource = $this->getStableTag($configBranch); + protected function getUpdateDetectionStrategies($configBranch) { + $strategies = array( + self::STRATEGY_STABLE_TAG => function () use ($configBranch) { + return $this->getStableTag($configBranch); + }, + ); - //Look for version-like tags. - if ( !$updateSource && ($configBranch === 'master' || $configBranch === 'main') ) { - $updateSource = $this->getLatestTag(); - } - //If all else fails, use the specified branch itself. - if ( !$updateSource ) { - $updateSource = $this->getBranch($configBranch); + if ( ($configBranch === 'master' || $configBranch === 'main') ) { + $strategies[self::STRATEGY_LATEST_TAG] = array($this, 'getLatestTag'); } - return $updateSource; + $strategies[self::STRATEGY_BRANCH] = function () use ($configBranch) { + return $this->getBranch($configBranch); + }; + return $strategies; } public function getBranch($branchName) { @@ -67,7 +66,7 @@ public function getBranch($branchName) { $ref = $branch->target->hash; } - return new Puc_v4p13_Vcs_Reference(array( + return new Reference(array( 'name' => $ref, 'updated' => $branch->target->date, 'downloadUrl' => $this->getDownloadUrl($branch->name), @@ -78,7 +77,7 @@ public function getBranch($branchName) { * Get a specific tag. * * @param string $tagName - * @return Puc_v4p13_Vcs_Reference|null + * @return Reference|null */ public function getTag($tagName) { $tag = $this->api('/refs/tags/' . $tagName); @@ -86,7 +85,7 @@ public function getTag($tagName) { return null; } - return new Puc_v4p13_Vcs_Reference(array( + return new Reference(array( 'name' => $tag->name, 'version' => ltrim($tag->name, 'v'), 'updated' => $tag->target->date, @@ -97,7 +96,7 @@ public function getTag($tagName) { /** * Get the tag that looks like the highest version number. * - * @return Puc_v4p13_Vcs_Reference|null + * @return Reference|null */ public function getLatestTag() { $tags = $this->api('/refs/tags?sort=-target.date'); @@ -111,7 +110,7 @@ public function getLatestTag() { //Return the first result. if ( !empty($versionTags) ) { $tag = $versionTags[0]; - return new Puc_v4p13_Vcs_Reference(array( + return new Reference(array( 'name' => $tag->name, 'version' => ltrim($tag->name, 'v'), 'updated' => $tag->target->date, @@ -125,7 +124,7 @@ public function getLatestTag() { * Get the tag/ref specified by the "Stable tag" header in the readme.txt of a given branch. * * @param string $branch - * @return null|Puc_v4p13_Vcs_Reference + * @return null|Reference */ protected function getStableTag($branch) { $remoteReadme = $this->getRemoteReadme($branch); @@ -191,11 +190,11 @@ public function getLatestCommitTime($ref) { * * @param string $url * @param string $version - * @return mixed|WP_Error + * @return mixed|\WP_Error */ public function api($url, $version = '2.0') { $url = ltrim($url, '/'); - $isSrcResource = Puc_v4p13_Utils::startsWith($url, 'src/'); + $isSrcResource = Utils::startsWith($url, 'src/'); $url = implode('/', array( 'https://api.bitbucket.org', @@ -211,7 +210,7 @@ public function api($url, $version = '2.0') { $url = $this->oauth->sign($url,'GET'); } - $options = array('timeout' => 10); + $options = array('timeout' => wp_doing_cron() ? 10 : 3); if ( !empty($this->httpFilterName) ) { $options = apply_filters($this->httpFilterName, $options); } @@ -234,7 +233,7 @@ public function api($url, $version = '2.0') { return $document; } - $error = new WP_Error( + $error = new \WP_Error( 'puc-bitbucket-http-error', sprintf('BitBucket API error. Base URL: "%s", HTTP status code: %d.', $baseUrl, $code) ); @@ -250,7 +249,7 @@ public function setAuthentication($credentials) { parent::setAuthentication($credentials); if ( !empty($credentials) && !empty($credentials['consumer_key']) ) { - $this->oauth = new Puc_v4p13_OAuthSignature( + $this->oauth = new OAuthSignature( $credentials['consumer_key'], $credentials['consumer_secret'] ); @@ -261,7 +260,7 @@ public function setAuthentication($credentials) { public function signDownloadUrl($url) { //Add authentication data to download URLs. Since OAuth signatures incorporate - //timestamps, we have to do this immediately before inserting the update. Otherwise + //timestamps, we have to do this immediately before inserting the update. Otherwise, //authentication could fail due to a stale timestamp. if ( $this->oauth ) { $url = $this->oauth->sign($url); diff --git a/vendor/yahnis-elsts/plugin-update-checker/Puc/v4p13/Vcs/GitHubApi.php b/vendor/yahnis-elsts/plugin-update-checker/Puc/v5p1/Vcs/GitHubApi.php similarity index 64% rename from vendor/yahnis-elsts/plugin-update-checker/Puc/v4p13/Vcs/GitHubApi.php rename to vendor/yahnis-elsts/plugin-update-checker/Puc/v5p1/Vcs/GitHubApi.php index 0fb0b05b3..364584b85 100644 --- a/vendor/yahnis-elsts/plugin-update-checker/Puc/v4p13/Vcs/GitHubApi.php +++ b/vendor/yahnis-elsts/plugin-update-checker/Puc/v5p1/Vcs/GitHubApi.php @@ -1,8 +1,15 @@ [^/]+?)/(?P[^/#?&]+?)/?$@', $path, $matches) ) { $this->userName = $matches['username']; $this->repositoryName = $matches['repository']; } else { - throw new InvalidArgumentException('Invalid GitHub repository URL: "' . $repositoryUrl . '"'); + throw new \InvalidArgumentException('Invalid GitHub repository URL: "' . $repositoryUrl . '"'); } parent::__construct($repositoryUrl, $accessToken); @@ -57,59 +49,112 @@ public function __construct($repositoryUrl, $accessToken = null) { /** * Get the latest release from GitHub. * - * @return Puc_v4p13_Vcs_Reference|null + * @return Reference|null */ public function getLatestRelease() { - $release = $this->api('/repos/:user/:repo/releases/latest'); - if ( is_wp_error($release) || !is_object($release) || !isset($release->tag_name) ) { - return null; + //The "latest release" endpoint returns one release and always skips pre-releases, + //so we can only use it if that's compatible with the current filter settings. + if ( + $this->shouldSkipPreReleases() + && ( + ($this->releaseFilterMaxReleases === 1) || !$this->hasCustomReleaseFilter() + ) + ) { + //Just get the latest release. + $release = $this->api('/repos/:user/:repo/releases/latest'); + if ( is_wp_error($release) || !is_object($release) || !isset($release->tag_name) ) { + return null; + } + $foundReleases = array($release); + } else { + //Get a list of the most recent releases. + $foundReleases = $this->api( + '/repos/:user/:repo/releases', + array('per_page' => $this->releaseFilterMaxReleases) + ); + if ( is_wp_error($foundReleases) || !is_array($foundReleases) ) { + return null; + } } - $reference = new Puc_v4p13_Vcs_Reference(array( - 'name' => $release->tag_name, - 'version' => ltrim($release->tag_name, 'v'), //Remove the "v" prefix from "v1.2.3". - 'downloadUrl' => $release->zipball_url, - 'updated' => $release->created_at, - 'apiResponse' => $release, - )); + foreach ($foundReleases as $release) { + //Always skip drafts. + if ( isset($release->draft) && !empty($release->draft) ) { + continue; + } - if ( isset($release->assets[0]) ) { - $reference->downloadCount = $release->assets[0]->download_count; - } + //Skip pre-releases unless specifically included. + if ( + $this->shouldSkipPreReleases() + && isset($release->prerelease) + && !empty($release->prerelease) + ) { + continue; + } + + $versionNumber = ltrim($release->tag_name, 'v'); //Remove the "v" prefix from "v1.2.3". + + //Custom release filtering. + if ( !$this->matchesCustomReleaseFilter($versionNumber, $release) ) { + continue; + } + + $reference = new Reference(array( + 'name' => $release->tag_name, + 'version' => $versionNumber, + 'downloadUrl' => $release->zipball_url, + 'updated' => $release->created_at, + 'apiResponse' => $release, + )); + + if ( isset($release->assets[0]) ) { + $reference->downloadCount = $release->assets[0]->download_count; + } - if ( $this->releaseAssetsEnabled && isset($release->assets, $release->assets[0]) ) { - //Use the first release asset that matches the specified regular expression. - $matchingAssets = array_filter($release->assets, array($this, 'matchesAssetFilter')); - if ( !empty($matchingAssets) ) { - if ( $this->isAuthenticationEnabled() ) { - /** - * Keep in mind that we'll need to add an "Accept" header to download this asset. - * - * @see setUpdateDownloadHeaders() - */ - $reference->downloadUrl = $matchingAssets[0]->url; + if ( $this->releaseAssetsEnabled ) { + //Use the first release asset that matches the specified regular expression. + if ( isset($release->assets, $release->assets[0]) ) { + $matchingAssets = array_values(array_filter($release->assets, array($this, 'matchesAssetFilter'))); } else { - //It seems that browser_download_url only works for public repositories. - //Using an access_token doesn't help. Maybe OAuth would work? - $reference->downloadUrl = $matchingAssets[0]->browser_download_url; + $matchingAssets = array(); } - $reference->downloadCount = $matchingAssets[0]->download_count; + if ( !empty($matchingAssets) ) { + if ( $this->isAuthenticationEnabled() ) { + /** + * Keep in mind that we'll need to add an "Accept" header to download this asset. + * + * @see setUpdateDownloadHeaders() + */ + $reference->downloadUrl = $matchingAssets[0]->url; + } else { + //It seems that browser_download_url only works for public repositories. + //Using an access_token doesn't help. Maybe OAuth would work? + $reference->downloadUrl = $matchingAssets[0]->browser_download_url; + } + + $reference->downloadCount = $matchingAssets[0]->download_count; + } else if ( $this->releaseAssetPreference === Api::REQUIRE_RELEASE_ASSETS ) { + //None of the assets match the filter, and we're not allowed + //to fall back to the auto-generated source ZIP. + return null; + } } - } - if ( !empty($release->body) ) { - /** @noinspection PhpUndefinedClassInspection */ - $reference->changelog = Parsedown::instance()->text($release->body); + if ( !empty($release->body) ) { + $reference->changelog = Parsedown::instance()->text($release->body); + } + + return $reference; } - return $reference; + return null; } /** * Get the tag that looks like the highest version number. * - * @return Puc_v4p13_Vcs_Reference|null + * @return Reference|null */ public function getLatestTag() { $tags = $this->api('/repos/:user/:repo/tags'); @@ -124,7 +169,7 @@ public function getLatestTag() { } $tag = $versionTags[0]; - return new Puc_v4p13_Vcs_Reference(array( + return new Reference(array( 'name' => $tag->name, 'version' => ltrim($tag->name, 'v'), 'downloadUrl' => $tag->zipball_url, @@ -136,7 +181,7 @@ public function getLatestTag() { * Get a branch by name. * * @param string $branchName - * @return null|Puc_v4p13_Vcs_Reference + * @return null|Reference */ public function getBranch($branchName) { $branch = $this->api('/repos/:user/:repo/branches/' . $branchName); @@ -144,7 +189,7 @@ public function getBranch($branchName) { return null; } - $reference = new Puc_v4p13_Vcs_Reference(array( + $reference = new Reference(array( 'name' => $branch->name, 'downloadUrl' => $this->buildArchiveDownloadUrl($branch->name), 'apiResponse' => $branch, @@ -162,7 +207,7 @@ public function getBranch($branchName) { * * @param string $filename * @param string $ref Reference name (e.g. branch or tag). - * @return StdClass|null + * @return \StdClass|null */ public function getLatestCommit($filename, $ref = 'master') { $commits = $this->api( @@ -197,13 +242,13 @@ public function getLatestCommitTime($ref) { * * @param string $url * @param array $queryParams - * @return mixed|WP_Error + * @return mixed|\WP_Error */ protected function api($url, $queryParams = array()) { $baseUrl = $url; $url = $this->buildApiUrl($url, $queryParams); - $options = array('timeout' => 10); + $options = array('timeout' => wp_doing_cron() ? 10 : 3); if ( $this->isAuthenticationEnabled() ) { $options['headers'] = array('Authorization' => $this->getAuthorizationHeader()); } @@ -224,7 +269,7 @@ protected function api($url, $queryParams = array()) { return $document; } - $error = new WP_Error( + $error = new \WP_Error( 'puc-github-http-error', sprintf('GitHub API error. Base URL: "%s", HTTP status code: %d.', $baseUrl, $code) ); @@ -298,7 +343,7 @@ public function buildArchiveDownloadUrl($ref = 'master') { */ public function getTag($tagName) { //The current GitHub update checker doesn't use getTag, so I didn't bother to implement it. - throw new LogicException('The ' . __METHOD__ . ' method is not implemented and should not be used.'); + throw new \LogicException('The ' . __METHOD__ . ' method is not implemented and should not be used.'); } public function setAuthentication($credentials) { @@ -310,72 +355,52 @@ public function setAuthentication($credentials) { add_filter('upgrader_pre_download', array($this, 'addHttpRequestFilter'), 10, 1); //WP 3.7+ } - /** - * Figure out which reference (i.e tag or branch) contains the latest version. - * - * @param string $configBranch Start looking in this branch. - * @return null|Puc_v4p13_Vcs_Reference - */ - public function chooseReference($configBranch) { - $updateSource = null; + protected function getUpdateDetectionStrategies($configBranch) { + $strategies = array(); - if ( $configBranch === 'master' ) { + if ( $configBranch === 'master' || $configBranch === 'main') { //Use the latest release. - $updateSource = $this->getLatestRelease(); - if ( $updateSource === null ) { - //Failing that, use the tag with the highest version number. - $updateSource = $this->getLatestTag(); - } + $strategies[self::STRATEGY_LATEST_RELEASE] = array($this, 'getLatestRelease'); + //Failing that, use the tag with the highest version number. + $strategies[self::STRATEGY_LATEST_TAG] = array($this, 'getLatestTag'); } + //Alternatively, just use the branch itself. - if ( empty($updateSource) ) { - $updateSource = $this->getBranch($configBranch); - } + $strategies[self::STRATEGY_BRANCH] = function () use ($configBranch) { + return $this->getBranch($configBranch); + }; - return $updateSource; + return $strategies; } /** - * Enable updating via release assets. + * Get the unchanging part of a release asset URL. Used to identify download attempts. * - * If the latest release contains no usable assets, the update checker - * will fall back to using the automatically generated ZIP archive. - * - * Private repositories will only work with WordPress 3.7 or later. - * - * @param string|null $fileNameRegex Optional. Use only those assets where the file name matches this regex. + * @return string */ - public function enableReleaseAssets($fileNameRegex = null) { - $this->releaseAssetsEnabled = true; - $this->assetFilterRegex = $fileNameRegex; - $this->assetApiBaseUrl = sprintf( + protected function getAssetApiBaseUrl() { + return sprintf( '//api.github.com/repos/%1$s/%2$s/releases/assets/', $this->userName, $this->repositoryName ); } - /** - * Does this asset match the file name regex? - * - * @param stdClass $releaseAsset - * @return bool - */ - protected function matchesAssetFilter($releaseAsset) { - if ( $this->assetFilterRegex === null ) { - //The default is to accept all assets. - return true; + protected function getFilterableAssetName($releaseAsset) { + if ( isset($releaseAsset->name) ) { + return $releaseAsset->name; } - return isset($releaseAsset->name) && preg_match($this->assetFilterRegex, $releaseAsset->name); + return null; } /** - * @internal * @param bool $result * @return bool + * @internal */ public function addHttpRequestFilter($result) { if ( !$this->downloadFilterAdded && $this->isAuthenticationEnabled() ) { + //phpcs:ignore WordPressVIPMinimum.Hooks.RestrictedHooks.http_request_args -- The callback doesn't change the timeout. add_filter('http_request_args', array($this, 'setUpdateDownloadHeaders'), 10, 2); add_action('requests-requests.before_redirect', array($this, 'removeAuthHeaderFromRedirects'), 10, 4); $this->downloadFilterAdded = true; @@ -387,6 +412,7 @@ public function addHttpRequestFilter($result) { * Set the HTTP headers that are necessary to download updates from private repositories. * * See GitHub docs: + * * @link https://developer.github.com/v3/repos/releases/#get-a-single-release-asset * @link https://developer.github.com/v3/auth/#basic-authentication * @@ -397,7 +423,7 @@ public function addHttpRequestFilter($result) { */ public function setUpdateDownloadHeaders($requestArgs, $url = '') { //Is WordPress trying to download one of our release assets? - if ( $this->releaseAssetsEnabled && (strpos($url, $this->assetApiBaseUrl) !== false) ) { + if ( $this->releaseAssetsEnabled && (strpos($url, $this->getAssetApiBaseUrl()) !== false) ) { $requestArgs['headers']['Accept'] = 'application/octet-stream'; } //Use Basic authentication, but only if the download is from our repository. @@ -413,9 +439,9 @@ public function setUpdateDownloadHeaders($requestArgs, $url = '') { * the authorization header to other hosts. We don't want that because it breaks * AWS downloads and can leak authorization information. * - * @internal * @param string $location * @param array $headers + * @internal */ public function removeAuthHeaderFromRedirects(&$location, &$headers) { $repoApiBaseUrl = $this->buildApiUrl('/repos/:user/:repo/', array()); diff --git a/vendor/yahnis-elsts/plugin-update-checker/Puc/v4p13/Vcs/GitLabApi.php b/vendor/yahnis-elsts/plugin-update-checker/Puc/v5p1/Vcs/GitLabApi.php similarity index 65% rename from vendor/yahnis-elsts/plugin-update-checker/Puc/v4p13/Vcs/GitLabApi.php rename to vendor/yahnis-elsts/plugin-update-checker/Puc/v5p1/Vcs/GitLabApi.php index cd90ec2ac..663c2e7ca 100644 --- a/vendor/yahnis-elsts/plugin-update-checker/Puc/v4p13/Vcs/GitLabApi.php +++ b/vendor/yahnis-elsts/plugin-update-checker/Puc/v5p1/Vcs/GitLabApi.php @@ -1,8 +1,13 @@ repositoryHost = parse_url($repositoryUrl, PHP_URL_HOST) . $port; + $this->repositoryHost = wp_parse_url($repositoryUrl, PHP_URL_HOST) . $port; if ( $this->repositoryHost !== 'gitlab.com' ) { - $this->repositoryProtocol = parse_url($repositoryUrl, PHP_URL_SCHEME); + $this->repositoryProtocol = wp_parse_url($repositoryUrl, PHP_URL_SCHEME); } //Find the repository information - $path = parse_url($repositoryUrl, PHP_URL_PATH); + $path = wp_parse_url($repositoryUrl, PHP_URL_PATH); if ( preg_match('@^/?(?P[^/]+?)/(?P[^/#?&]+?)/?$@', $path, $matches) ) { $this->userName = $matches['username']; $this->repositoryName = $matches['repository']; @@ -59,7 +60,7 @@ public function __construct($repositoryUrl, $accessToken = null, $subgroup = nul //This is probably a repository in a subgroup, e.g. "/organization/category/repo". $parts = explode('/', trim($path, '/')); if ( count($parts) < 3 ) { - throw new InvalidArgumentException('Invalid GitLab.com repository URL: "' . $repositoryUrl . '"'); + throw new \InvalidArgumentException('Invalid GitLab.com repository URL: "' . $repositoryUrl . '"'); } $lastPart = array_pop($parts); $this->userName = implode('/', $parts); @@ -76,7 +77,7 @@ public function __construct($repositoryUrl, $accessToken = null, $subgroup = nul //We need at least /user-name/repository-name/ if ( count($segments) < 2 ) { - throw new InvalidArgumentException('Invalid GitLab repository URL: "' . $repositoryUrl . '"'); + throw new \InvalidArgumentException('Invalid GitLab repository URL: "' . $repositoryUrl . '"'); } //Get the username and repository name. @@ -101,83 +102,92 @@ public function __construct($repositoryUrl, $accessToken = null, $subgroup = nul /** * Get the latest release from GitLab. * - * @return Puc_v4p13_Vcs_Reference|null + * @return Reference|null */ public function getLatestRelease() { - $releases = $this->api('/:id/releases'); + $releases = $this->api('/:id/releases', array('per_page' => $this->releaseFilterMaxReleases)); if ( is_wp_error($releases) || empty($releases) || !is_array($releases) ) { return null; } foreach ($releases as $release) { - if ( true !== $release->upcoming_release ) { - break 1; //Break the loop on the first release we find that isn't an upcoming release + if ( + //Skip invalid/unsupported releases. + !is_object($release) + || !isset($release->tag_name) + //Skip upcoming releases. + || ( + !empty($release->upcoming_release) + && $this->shouldSkipPreReleases() + ) + ) { + continue; } - } - if ( is_wp_error($release) || !is_object($release) || !isset($release->tag_name) ) { - return null; - } - $reference = new Puc_v4p13_Vcs_Reference(array( - 'name' => $release->tag_name, - 'version' => ltrim($release->tag_name, 'v'), //Remove the "v" prefix from "v1.2.3". - 'downloadUrl' => '', - 'updated' => $release->released_at, - 'apiResponse' => $release, - )); - $download_url = false; - - if ( $this->releasePackageEnabled && isset($release->assets, $release->assets->links) ) { - /** - * Use the first asset LINK that is a zip format file generated by a Gitlab Release Pipeline - * - * @link https://gist.github.com/timwiel/9dfd3526c768efad4973254085e065ce - */ - foreach ($release->assets->links as $link) { - //TODO: Check the "format" property instead of the URL suffix. - if ( 'zip' === substr($link->url, -3) ) { - $download_url = $link->url; - break 1; - } + $versionNumber = ltrim($release->tag_name, 'v'); //Remove the "v" prefix from "v1.2.3". + + //Apply custom filters. + if ( !$this->matchesCustomReleaseFilter($versionNumber, $release) ) { + continue; } - if ( empty( $download_url ) ) { + + $downloadUrl = $this->findReleaseDownloadUrl($release); + if ( empty($downloadUrl) ) { + //The latest release doesn't have valid download URL. return null; } - if ( ! empty( $this->accessToken ) ) { - $download_url = add_query_arg('private_token', $this->accessToken, $download_url); + + if ( !empty($this->accessToken) ) { + $downloadUrl = add_query_arg('private_token', $this->accessToken, $downloadUrl); } - $reference->downloadUrl = $download_url; - return $reference; - - } elseif ( isset($release->assets) ) { - /** - * Use the first asset SOURCE file that is a zip format from a Gitlab Release which should be a zip file - */ - foreach ($release->assets->sources as $source) { - if ( 'zip' === $source->format ) { - $download_url = $source->url; - break 1; + + return new Reference(array( + 'name' => $release->tag_name, + 'version' => $versionNumber, + 'downloadUrl' => $downloadUrl, + 'updated' => $release->released_at, + 'apiResponse' => $release, + )); + } + + return null; + } + + /** + * @param object $release + * @return string|null + */ + protected function findReleaseDownloadUrl($release) { + if ( $this->releaseAssetsEnabled ) { + if ( isset($release->assets, $release->assets->links) ) { + //Use the first asset link where the URL matches the filter. + foreach ($release->assets->links as $link) { + if ( $this->matchesAssetFilter($link) ) { + return $link->url; + } } } - if ( empty( $download_url ) ) { + + if ( $this->releaseAssetPreference === Api::REQUIRE_RELEASE_ASSETS ) { + //Falling back to source archives is not allowed, so give up. return null; } - if ( ! empty( $this->accessToken ) ) { - $download_url = add_query_arg('private_token', $this->accessToken, $download_url); - } - $reference->downloadUrl = $download_url; - return $reference; + } + //Use the first source code archive that's in ZIP format. + foreach ($release->assets->sources as $source) { + if ( isset($source->format) && ($source->format === 'zip') ) { + return $source->url; + } } - //If we get this far without a return then obviosuly noi release download urls were found return null; - } + } /** * Get the tag that looks like the highest version number. * - * @return Puc_v4p13_Vcs_Reference|null + * @return Reference|null */ public function getLatestTag() { $tags = $this->api('/:id/repository/tags'); @@ -191,7 +201,7 @@ public function getLatestTag() { } $tag = $versionTags[0]; - return new Puc_v4p13_Vcs_Reference(array( + return new Reference(array( 'name' => $tag->name, 'version' => ltrim($tag->name, 'v'), 'downloadUrl' => $this->buildArchiveDownloadUrl($tag->name), @@ -203,7 +213,7 @@ public function getLatestTag() { * Get a branch by name. * * @param string $branchName - * @return null|Puc_v4p13_Vcs_Reference + * @return null|Reference */ public function getBranch($branchName) { $branch = $this->api('/:id/repository/branches/' . $branchName); @@ -211,7 +221,7 @@ public function getBranch($branchName) { return null; } - $reference = new Puc_v4p13_Vcs_Reference(array( + $reference = new Reference(array( 'name' => $branch->name, 'downloadUrl' => $this->buildArchiveDownloadUrl($branch->name), 'apiResponse' => $branch, @@ -244,13 +254,13 @@ public function getLatestCommitTime($ref) { * * @param string $url * @param array $queryParams - * @return mixed|WP_Error + * @return mixed|\WP_Error */ protected function api($url, $queryParams = array()) { $baseUrl = $url; $url = $this->buildApiUrl($url, $queryParams); - $options = array('timeout' => 10); + $options = array('timeout' => wp_doing_cron() ? 10 : 3); if ( !empty($this->httpFilterName) ) { $options = apply_filters($this->httpFilterName, $options); } @@ -267,7 +277,7 @@ protected function api($url, $queryParams = array()) { return json_decode($body); } - $error = new WP_Error( + $error = new \WP_Error( 'puc-gitlab-http-error', sprintf('GitLab API error. URL: "%s", HTTP status code: %d.', $baseUrl, $code) ); @@ -353,31 +363,22 @@ public function buildArchiveDownloadUrl($ref = 'master') { * @return void */ public function getTag($tagName) { - throw new LogicException('The ' . __METHOD__ . ' method is not implemented and should not be used.'); + throw new \LogicException('The ' . __METHOD__ . ' method is not implemented and should not be used.'); } - /** - * Figure out which reference (i.e tag or branch) contains the latest version. - * - * @param string $configBranch Start looking in this branch. - * @return null|Puc_v4p13_Vcs_Reference - */ - public function chooseReference($configBranch) { - - if ( $configBranch === 'main' || $configBranch === 'master' ) { - //Use the latest release. - $updateSource = $this->getLatestRelease(); - if ( $updateSource === null ) { - //Failing that, use the tag with the highest version number. - $updateSource = $this->getLatestTag(); - } - } - //Alternatively, just use the branch itself. - if ( empty($updateSource) ) { - $updateSource = $this->getBranch($configBranch); + protected function getUpdateDetectionStrategies($configBranch) { + $strategies = array(); + + if ( ($configBranch === 'main') || ($configBranch === 'master') ) { + $strategies[self::STRATEGY_LATEST_RELEASE] = array($this, 'getLatestRelease'); + $strategies[self::STRATEGY_LATEST_TAG] = array($this, 'getLatestTag'); } - return $updateSource; + $strategies[self::STRATEGY_BRANCH] = function () use ($configBranch) { + return $this->getBranch($configBranch); + }; + + return $strategies; } public function setAuthentication($credentials) { @@ -385,16 +386,29 @@ public function setAuthentication($credentials) { $this->accessToken = is_string($credentials) ? $credentials : null; } - public function enableReleaseAssets() { - $this->releaseAssetsEnabled = true; - $this->releasePackageEnabled = false; - } - + /** + * Use release assets that link to GitLab generic packages (e.g. .zip files) + * instead of automatically generated source archives. + * + * This is included for backwards compatibility with older versions of PUC. + * + * @return void + * @deprecated Use enableReleaseAssets() instead. + * @noinspection PhpUnused -- Public API + */ public function enableReleasePackages() { - $this->releaseAssetsEnabled = false; - $this->releasePackageEnabled = true; + $this->enableReleaseAssets( + /** @lang RegExp */ '/\.zip($|[?&#])/i', + Api::REQUIRE_RELEASE_ASSETS + ); } + protected function getFilterableAssetName($releaseAsset) { + if ( isset($releaseAsset->url) ) { + return $releaseAsset->url; + } + return null; + } } endif; diff --git a/vendor/yahnis-elsts/plugin-update-checker/Puc/v4p13/Vcs/PluginUpdateChecker.php b/vendor/yahnis-elsts/plugin-update-checker/Puc/v5p1/Vcs/PluginUpdateChecker.php similarity index 84% rename from vendor/yahnis-elsts/plugin-update-checker/Puc/v4p13/Vcs/PluginUpdateChecker.php rename to vendor/yahnis-elsts/plugin-update-checker/Puc/v5p1/Vcs/PluginUpdateChecker.php index 33d914294..082a847f6 100644 --- a/vendor/yahnis-elsts/plugin-update-checker/Puc/v4p13/Vcs/PluginUpdateChecker.php +++ b/vendor/yahnis-elsts/plugin-update-checker/Puc/v5p1/Vcs/PluginUpdateChecker.php @@ -1,21 +1,18 @@ api = $api; - $this->api->setHttpFilterName($this->getUniqueName('request_info_options')); parent::__construct($api->getRepositoryUrl(), $pluginFile, $slug, $checkPeriod, $optionName, $muPluginFile); + $this->api->setHttpFilterName($this->getUniqueName('request_info_options')); + $this->api->setStrategyFilterName($this->getUniqueName('vcs_update_detection_strategies')); $this->api->setSlug($this->slug); } @@ -41,7 +39,7 @@ public function requestInfo($unusedParameter = null) { $api = $this->api; $api->setLocalDirectory($this->package->getAbsoluteDirectoryPath()); - $info = new Puc_v4p13_Plugin_Info(); + $info = new Plugin\PluginInfo(); $info->filename = $this->pluginFile; $info->slug = $this->slug; @@ -67,7 +65,7 @@ public function requestInfo($unusedParameter = null) { //There's probably a network problem or an authentication error. do_action( 'puc_api_error', - new WP_Error( + new \WP_Error( 'puc-no-update-source', 'Could not retrieve version information from the repository. ' . 'This usually means that the update checker either can\'t connect ' @@ -126,7 +124,7 @@ protected function readmeTxtExistsLocally() { * Copy plugin metadata from a file header to a Plugin Info object. * * @param array $fileHeader - * @param Puc_v4p13_Plugin_Info $pluginInfo + * @param Plugin\PluginInfo $pluginInfo */ protected function setInfoFromHeader($fileHeader, $pluginInfo) { $headerToPropertyMap = array( @@ -159,7 +157,7 @@ protected function setInfoFromHeader($fileHeader, $pluginInfo) { * Copy plugin metadata from the remote readme.txt file. * * @param string $ref GitHub tag or branch where to look for the readme. - * @param Puc_v4p13_Plugin_Info $pluginInfo + * @param Plugin\PluginInfo $pluginInfo */ protected function setInfoFromRemoteReadme($ref, $pluginInfo) { $readme = $this->api->getRemoteReadme($ref); @@ -192,7 +190,7 @@ protected function setInfoFromRemoteReadme($ref, $pluginInfo) { * and file names are described here: * @link https://developer.wordpress.org/plugins/wordpress-org/plugin-assets/#plugin-icons * - * @param Puc_v4p13_Plugin_Info $pluginInfo + * @param Plugin\PluginInfo $pluginInfo */ protected function setIconsFromLocalAssets($pluginInfo) { $icons = $this->getLocalAssetUrls(array( @@ -221,7 +219,7 @@ protected function setIconsFromLocalAssets($pluginInfo) { * and file names are described here: * @link https://developer.wordpress.org/plugins/wordpress-org/plugin-assets/#plugin-headers * - * @param Puc_v4p13_Plugin_Info $pluginInfo + * @param Plugin\PluginInfo $pluginInfo */ protected function setBannersFromLocalAssets($pluginInfo) { $banners = $this->getLocalAssetUrls(array( @@ -257,37 +255,6 @@ protected function getLocalAssetUrls($filesToKeys) { return $foundAssets; } - - public function setBranch($branch) { - $this->branch = $branch; - return $this; - } - - public function setAuthentication($credentials) { - $this->api->setAuthentication($credentials); - return $this; - } - - public function getVcsApi() { - return $this->api; - } - - public function getUpdate() { - $update = parent::getUpdate(); - - if ( isset($update) && !empty($update->download_url) ) { - $update->download_url = $this->api->signDownloadUrl($update->download_url); - } - - return $update; - } - - public function onDisplayConfiguration($panel) { - parent::onDisplayConfiguration($panel); - $panel->row('Branch', $this->branch); - $panel->row('Authentication enabled', $this->api->isAuthenticationEnabled() ? 'Yes' : 'No'); - $panel->row('API client', get_class($this->api)); - } } endif; diff --git a/vendor/yahnis-elsts/plugin-update-checker/Puc/v4p13/Vcs/Reference.php b/vendor/yahnis-elsts/plugin-update-checker/Puc/v5p1/Vcs/Reference.php similarity index 89% rename from vendor/yahnis-elsts/plugin-update-checker/Puc/v4p13/Vcs/Reference.php rename to vendor/yahnis-elsts/plugin-update-checker/Puc/v5p1/Vcs/Reference.php index 925116586..6cff32a45 100644 --- a/vendor/yahnis-elsts/plugin-update-checker/Puc/v4p13/Vcs/Reference.php +++ b/vendor/yahnis-elsts/plugin-update-checker/Puc/v5p1/Vcs/Reference.php @@ -1,5 +1,7 @@ releaseAssetsEnabled = true; + $this->assetFilterRegex = $nameRegex; + $this->releaseAssetPreference = $preference; + } + + /** + * Disable release assets. + * + * @return void + * @noinspection PhpUnused -- Public API + */ + public function disableReleaseAssets() { + $this->releaseAssetsEnabled = false; + $this->assetFilterRegex = null; + } + + /** + * Does the specified asset match the name regex? + * + * @param mixed $releaseAsset Data type and structure depend on the host/API. + * @return bool + */ + protected function matchesAssetFilter($releaseAsset) { + if ( $this->assetFilterRegex === null ) { + //The default is to accept all assets. + return true; + } + + $name = $this->getFilterableAssetName($releaseAsset); + if ( !is_string($name) ) { + return false; + } + return (bool)preg_match($this->assetFilterRegex, $releaseAsset->name); + } + + /** + * Get the part of asset data that will be checked against the filter regex. + * + * @param mixed $releaseAsset + * @return string|null + */ + abstract protected function getFilterableAssetName($releaseAsset); + } + +endif; \ No newline at end of file diff --git a/vendor/yahnis-elsts/plugin-update-checker/Puc/v5p1/Vcs/ReleaseFilteringFeature.php b/vendor/yahnis-elsts/plugin-update-checker/Puc/v5p1/Vcs/ReleaseFilteringFeature.php new file mode 100644 index 000000000..12ef54ed6 --- /dev/null +++ b/vendor/yahnis-elsts/plugin-update-checker/Puc/v5p1/Vcs/ReleaseFilteringFeature.php @@ -0,0 +1,108 @@ + 100 ) { + throw new \InvalidArgumentException(sprintf( + 'The max number of releases is too high (%d). It must be 100 or less.', + $maxReleases + )); + } else if ( $maxReleases < 1 ) { + throw new \InvalidArgumentException(sprintf( + 'The max number of releases is too low (%d). It must be at least 1.', + $maxReleases + )); + } + + $this->releaseFilterCallback = $callback; + $this->releaseFilterByType = $releaseTypes; + $this->releaseFilterMaxReleases = $maxReleases; + return $this; + } + + /** + * Filter releases by their version number. + * + * @param string $regex A regular expression. The release version number must match this regex. + * @param int $releaseTypes + * @param int $maxReleasesToExamine + * @return $this + * @noinspection PhpUnused -- Public API + */ + public function setReleaseVersionFilter( + $regex, + $releaseTypes = Api::RELEASE_FILTER_SKIP_PRERELEASE, + $maxReleasesToExamine = 20 + ) { + return $this->setReleaseFilter( + function ($versionNumber) use ($regex) { + return (preg_match($regex, $versionNumber) === 1); + }, + $releaseTypes, + $maxReleasesToExamine + ); + } + + /** + * @param string $versionNumber The detected release version number. + * @param object $releaseObject Varies depending on the host/API. + * @return bool + */ + protected function matchesCustomReleaseFilter($versionNumber, $releaseObject) { + if ( !is_callable($this->releaseFilterCallback) ) { + return true; //No custom filter. + } + return call_user_func($this->releaseFilterCallback, $versionNumber, $releaseObject); + } + + /** + * @return bool + */ + protected function shouldSkipPreReleases() { + //Maybe this could be a bitfield in the future, if we need to support + //more release types. + return ($this->releaseFilterByType !== Api::RELEASE_FILTER_ALL); + } + + /** + * @return bool + */ + protected function hasCustomReleaseFilter() { + return isset($this->releaseFilterCallback) && is_callable($this->releaseFilterCallback); + } + } + +endif; \ No newline at end of file diff --git a/vendor/yahnis-elsts/plugin-update-checker/Puc/v4p13/Vcs/ThemeUpdateChecker.php b/vendor/yahnis-elsts/plugin-update-checker/Puc/v5p1/Vcs/ThemeUpdateChecker.php similarity index 55% rename from vendor/yahnis-elsts/plugin-update-checker/Puc/v4p13/Vcs/ThemeUpdateChecker.php rename to vendor/yahnis-elsts/plugin-update-checker/Puc/v5p1/Vcs/ThemeUpdateChecker.php index c463b8e5f..c871ce9fe 100644 --- a/vendor/yahnis-elsts/plugin-update-checker/Puc/v4p13/Vcs/ThemeUpdateChecker.php +++ b/vendor/yahnis-elsts/plugin-update-checker/Puc/v5p1/Vcs/ThemeUpdateChecker.php @@ -1,22 +1,19 @@ api = $api; - $this->api->setHttpFilterName($this->getUniqueName('request_update_options')); parent::__construct($api->getRepositoryUrl(), $stylesheet, $customSlug, $checkPeriod, $optionName); + $this->api->setHttpFilterName($this->getUniqueName('request_update_options')); + $this->api->setStrategyFilterName($this->getUniqueName('vcs_update_detection_strategies')); $this->api->setSlug($this->slug); } @@ -35,7 +33,7 @@ public function requestUpdate() { $api = $this->api; $api->setLocalDirectory($this->package->getAbsoluteDirectoryPath()); - $update = new Puc_v4p13_Theme_Update(); + $update = new Theme\Update(); $update->slug = $this->slug; //Figure out which reference (tag or branch) we'll use to get the latest version of the theme. @@ -46,7 +44,7 @@ public function requestUpdate() { } else { do_action( 'puc_api_error', - new WP_Error( + new \WP_Error( 'puc-no-update-source', 'Could not retrieve version information from the repository. ' . 'This usually means that the update checker either can\'t connect ' @@ -60,13 +58,13 @@ public function requestUpdate() { //Get headers from the main stylesheet in this branch/tag. Its "Version" header and other metadata //are what the WordPress install will actually see after upgrading, so they take precedence over releases/tags. $remoteHeader = $this->package->getFileHeader($api->getRemoteFile('style.css', $ref)); - $update->version = Puc_v4p13_Utils::findNotEmpty(array( + $update->version = Utils::findNotEmpty(array( $remoteHeader['Version'], - Puc_v4p13_Utils::get($updateSource, 'version'), + Utils::get($updateSource, 'version'), )); //The details URL defaults to the Theme URI header or the repository URL. - $update->details_url = Puc_v4p13_Utils::findNotEmpty(array( + $update->details_url = Utils::findNotEmpty(array( $remoteHeader['ThemeURI'], $this->package->getHeaderValue('ThemeURI'), $this->metadataUrl, @@ -80,39 +78,6 @@ public function requestUpdate() { $update = $this->filterUpdateResult($update); return $update; } - - //FIXME: This is duplicated code. Both theme and plugin subclasses that use VCS share these methods. - - public function setBranch($branch) { - $this->branch = $branch; - return $this; - } - - public function setAuthentication($credentials) { - $this->api->setAuthentication($credentials); - return $this; - } - - public function getVcsApi() { - return $this->api; - } - - public function getUpdate() { - $update = parent::getUpdate(); - - if ( isset($update) && !empty($update->download_url) ) { - $update->download_url = $this->api->signDownloadUrl($update->download_url); - } - - return $update; - } - - public function onDisplayConfiguration($panel) { - parent::onDisplayConfiguration($panel); - $panel->row('Branch', $this->branch); - $panel->row('Authentication enabled', $this->api->isAuthenticationEnabled() ? 'Yes' : 'No'); - $panel->row('API client', get_class($this->api)); - } } endif; diff --git a/vendor/yahnis-elsts/plugin-update-checker/Puc/v5p1/Vcs/VcsCheckerMethods.php b/vendor/yahnis-elsts/plugin-update-checker/Puc/v5p1/Vcs/VcsCheckerMethods.php new file mode 100644 index 000000000..113d663bc --- /dev/null +++ b/vendor/yahnis-elsts/plugin-update-checker/Puc/v5p1/Vcs/VcsCheckerMethods.php @@ -0,0 +1,59 @@ +branch = $branch; + return $this; + } + + /** + * Set authentication credentials. + * + * @param array|string $credentials + * @return $this + */ + public function setAuthentication($credentials) { + $this->api->setAuthentication($credentials); + return $this; + } + + /** + * @return Api + */ + public function getVcsApi() { + return $this->api; + } + + public function getUpdate() { + $update = parent::getUpdate(); + + if ( isset($update) && !empty($update->download_url) ) { + $update->download_url = $this->api->signDownloadUrl($update->download_url); + } + + return $update; + } + + public function onDisplayConfiguration($panel) { + parent::onDisplayConfiguration($panel); + $panel->row('Branch', $this->branch); + $panel->row('Authentication enabled', $this->api->isAuthenticationEnabled() ? 'Yes' : 'No'); + $panel->row('API client', get_class($this->api)); + } + } + +endif; \ No newline at end of file diff --git a/vendor/yahnis-elsts/plugin-update-checker/README.md b/vendor/yahnis-elsts/plugin-update-checker/README.md index 469564fc9..5a3b4b2d4 100644 --- a/vendor/yahnis-elsts/plugin-update-checker/README.md +++ b/vendor/yahnis-elsts/plugin-update-checker/README.md @@ -20,6 +20,7 @@ From the users' perspective, it works just like with plugins and themes hosted o - [How to Release an Update](#how-to-release-an-update-2) - [GitLab Integration](#gitlab-integration) - [How to Release a GitLab Update](#how-to-release-a-gitlab-update) +- [Migrating from 4.x](#migrating-from-4x) - [License Management](#license-management) - [Resources](#resources) @@ -40,7 +41,7 @@ Getting Started { "name" : "Plugin Name", "version" : "2.0", - "download_url" : "http://example.com/plugin-name-2.0.zip", + "download_url" : "https://example.com/plugin-name-2.0.zip", "sections" : { "description" : "Plugin description here. You can use HTML." } @@ -53,8 +54,8 @@ Getting Started ```json { "version": "2.0", - "details_url": "http://example.com/version-2.0-details.html", - "download_url": "http://example.com/example-theme-2.0.zip" + "details_url": "https://example.com/version-2.0-details.html", + "download_url": "https://example.com/example-theme-2.0.zip" } ``` @@ -64,8 +65,10 @@ Getting Started ```php require 'path/to/plugin-update-checker/plugin-update-checker.php'; - $myUpdateChecker = Puc_v4_Factory::buildUpdateChecker( - 'http://example.com/path/to/details.json', + use YahnisElsts\PluginUpdateChecker\v5\PucFactory; + + $myUpdateChecker = PucFactory::buildUpdateChecker( + 'https://example.com/path/to/details.json', __FILE__, //Full path to the main plugin file or functions.php. 'unique-plugin-or-theme-slug' ); @@ -96,7 +99,9 @@ By default, the library will check the specified URL for changes every 12 hours. ```php require 'plugin-update-checker/plugin-update-checker.php'; - $myUpdateChecker = Puc_v4_Factory::buildUpdateChecker( + use YahnisElsts\PluginUpdateChecker\v5\PucFactory; + + $myUpdateChecker = PucFactory::buildUpdateChecker( 'https://github.com/user-name/repo-name/', __FILE__, 'unique-plugin-or-theme-slug' @@ -127,7 +132,7 @@ This library supports a couple of different ways to release updates on GitHub. P To release version 1.2.3, create a new Git tag named `v1.2.3` or `1.2.3`. That's it. - PUC doesn't require strict adherence to [SemVer](http://semver.org/). These are all valid tag names: `v1.2.3`, `v1.2-foo`, `1.2.3_rc1-ABC`, `1.2.3.4.5`. However, be warned that it's not smart enough to filter out alpha/beta/RC versions. If that's a problem, you might want to use GitHub releases or branches instead. + PUC doesn't require strict adherence to [SemVer](https://semver.org/). These are all valid tag names: `v1.2.3`, `v1.2-foo`, `1.2.3_rc1-ABC`, `1.2.3.4.5`. However, be warned that it's not smart enough to filter out alpha/beta/RC versions. If that's a problem, you might want to use GitHub releases or branches instead. - **Stable branch** @@ -175,7 +180,9 @@ The library will pull update details from the following parts of a release/tag/b ```php require 'plugin-update-checker/plugin-update-checker.php'; - $myUpdateChecker = Puc_v4_Factory::buildUpdateChecker( + use YahnisElsts\PluginUpdateChecker\v5\PucFactory; + + $myUpdateChecker = PucFactory::buildUpdateChecker( 'https://bitbucket.org/user-name/repo-name', __FILE__, 'unique-plugin-or-theme-slug' @@ -214,7 +221,7 @@ BitBucket doesn't have an equivalent to GitHub's releases, so the process is sli You can skip the "stable tag" bit and just create a new Git tag named `v1.2.3` or `1.2.3`. The update checker will look at the most recent tags and pick the one that looks like the highest version number. - PUC doesn't require strict adherence to [SemVer](http://semver.org/). These are all valid tag names: `v1.2.3`, `v1.2-foo`, `1.2.3_rc1-ABC`, `1.2.3.4.5`. However, be warned that it's not smart enough to filter out alpha/beta/RC versions. + PUC doesn't require strict adherence to [SemVer](https://semver.org/). These are all valid tag names: `v1.2.3`, `v1.2-foo`, `1.2.3_rc1-ABC`, `1.2.3.4.5`. However, be warned that it's not smart enough to filter out alpha/beta/RC versions. - **Stable branch** @@ -231,7 +238,9 @@ BitBucket doesn't have an equivalent to GitHub's releases, so the process is sli ```php require 'plugin-update-checker/plugin-update-checker.php'; - $myUpdateChecker = Puc_v4_Factory::buildUpdateChecker( + use YahnisElsts\PluginUpdateChecker\v5\PucFactory; + + $myUpdateChecker = PucFactory::buildUpdateChecker( 'https://gitlab.com/user-name/repo-name/', __FILE__, 'unique-plugin-or-theme-slug' @@ -243,72 +252,109 @@ BitBucket doesn't have an equivalent to GitHub's releases, so the process is sli Alternatively, if you're using a self-hosted GitLab instance, initialize the update checker like this: ```php - $myUpdateChecker = new Puc_v4p13_Vcs_PluginUpdateChecker( - new Puc_v4p13_Vcs_GitLabApi('https://myserver.com/user-name/repo-name/'), - __FILE__, - 'unique-plugin-or-theme-slug' - ); - //Optional: Add setAuthentication(...) and setBranch(...) as shown above. - ``` - If you're using a self-hosted GitLab instance and [subgroups or nested groups](https://docs.gitlab.com/ce/user/group/subgroups/index.html), you have to tell the update checker which parts of the URL are subgroups: - ```php - $myUpdateChecker = new Puc_v4p13_Vcs_PluginUpdateChecker( - new Puc_v4p13_Vcs_GitLabApi('https://myserver.com/group-name/subgroup-level1/subgroup-level2/subgroup-level3/repo-name/', null, 'subgroup-level1/subgroup-level2/subgroup-level3'), - __FILE__, - 'unique-plugin-or-theme-slug' - ); - - ``` + use YahnisElsts\PluginUpdateChecker\v5p1\Vcs\PluginUpdateChecker; + use YahnisElsts\PluginUpdateChecker\v5p1\Vcs\GitLabApi; + + $myUpdateChecker = new PluginUpdateChecker( + new GitLabApi('https://myserver.com/user-name/repo-name/'), + __FILE__, + 'unique-plugin-or-theme-slug' + ); + //Optional: Add setAuthentication(...) and setBranch(...) as shown above. + ``` + If you're using a self-hosted GitLab instance and [subgroups or nested groups](https://docs.gitlab.com/ce/user/group/subgroups/index.html), you have to tell the update checker which parts of the URL are subgroups: + ```php + use YahnisElsts\PluginUpdateChecker\v5p1\Vcs\PluginUpdateChecker; + use YahnisElsts\PluginUpdateChecker\v5p1\Vcs\GitLabApi; + + $myUpdateChecker = new PluginUpdateChecker( + new GitLabApi( + 'https://myserver.com/group-name/subgroup-level1/subgroup-level2/subgroup-level3/repo-name/', + null, + 'subgroup-level1/subgroup-level2/subgroup-level3' + ), + __FILE__, + 'unique-plugin-or-theme-slug' + ); + ``` 3. Plugins only: Add a `readme.txt` file formatted according to the [WordPress.org plugin readme standard](https://wordpress.org/plugins/readme.txt) to your repository. The contents of this file will be shown when the user clicks the "View version 1.2.3 details" link. #### How to Release a GitLab Update -A Gitlab repository can be checked for updates in 4 different ways. - -1. **Stable branch** (other than `master` or `main`): - - Point the update checker at any stable, production-ready branch and PUC will periodically check the `Version` header in the main plugin file or `style.css` and display a notification if it's greater than the installed version. - - Add the following code: - ```php - //Add the following code to your main plugin file or `functions.php` file to check for updates from a custom branch - $myUpdateChecker->setBranch('stable-branch-name'); - ``` - - Caveats: - - If you set the branch to `main` (the default) or `master` (the historical default), the update checker will look for recent releases and tags first. It'll only use the `main` or `master` branch if it doesn't find anything else suitable. - -2. **GitLab Releases using Generic Packages**: - - Use a Gitlab CI/CD Pipeline to automatically generate your update on release using a Generic Package. The benefit of using Generic Package assets over the Source Code assets is that the code can already be built and production ready. - - Add the following code: - ```php - //Add the following code to your main plugin file or `functions.php` file to check for a new update from releases using generic packages - $myUpdateChecker->getVcsApi()->enableReleasePackages(); - ``` - - PUC will periodically check the release version (i.e. the tag name of the release) and will display a notification if the release is a greater version than the installed version. - - The release tag name should loosely follow [SemVer](http://semver.org/) but these are all valid release names: `v1.2.3`, `v1.2-foo`, `1.2.3_rc1-ABC`, `1.2.3.4.5` However, be warned that it's not smart enough to filter out alpha/beta/RC versions. If that's a problem, you might want to use GitLab branches instead. - - For more information about *Gitlab Release Generic Packages* refer to the following links: + +A GitLab repository can be checked for updates in 3 different ways. + +- **GitLab releases** + + Create a new release using the "Releases" feature on GitLab. The tag name should match the version number. You can add a `v` prefix to the tag, like `v1.2.3`. Releases that are marked as ["Upcoming Release"](https://docs.gitlab.com/ee/user/project/releases/index.html#upcoming-releases) will be automatically ignored. + + If you want to use custom release assets, call the `enableReleaseAssets()` method after creating the update checker instance: + ```php + $myUpdateChecker->getVcsApi()->enableReleaseAssets(); + ``` + + By default, PUC will use the first available asset link, regardless of type. You can pass a regular expression to `enableReleaseAssets()` to make it pick the first link where the URL matches the regex. For example: + ```php + $myUpdateChecker->getVcsApi()->enableReleaseAssets('/\.zip($|[?&#])/i'); + ``` + + **Tip:** You can use a Gitlab CI/CD Pipeline to automatically generate your update on release using a Generic Package. For more information about generic packages, refer to the following links: - [Gitlab CI/CD Release Documentation](https://docs.gitlab.com/ee/user/project/releases/#create-release-from-gitlab-ci) - [Gitlab Release Assets as Generic Package Documentation](https://gitlab.com/gitlab-org/release-cli/-/tree/master/docs/examples/release-assets-as-generic-package/) - [Example .gitlab-ci.yml file using Release Generic Packages for generating a update package from the Sensei-LMS wordpress plugin](https://gist.github.com/timwiel/9dfd3526c768efad4973254085e065ce) +- **Tags** -3. **GitLab Releases using Source Code Assets**: - - Create a new release using the "Releases" feature on Gitlab. - - Add the following code: - ```php - //Add the following code to your main plugin file or `functions.php` file to check for a new update from releases using release assets - $myUpdateChecker->getVcsApi()->enableReleaseAssets(); - ``` - - PUC will periodically check the release version (based on release tag name) and display a notification if the release version is greater than the installed version. - - The release name should loosely follow [SemVer](http://semver.org/) but these are all valid release names: `v1.2.3`, `v1.2-foo`, `1.2.3_rc1-ABC`, `1.2.3.4.5` However, be warned that it's not smart enough to filter out alpha/beta/RC versions. If that's a problem, you might want to use GitLab branches instead. + To release version 1.2.3, create a new Git tag named `v1.2.3` or `1.2.3`. The update checker will look at recent tags and use the one that looks like the highest version number. + + PUC doesn't require strict adherence to [SemVer](https://semver.org/). However, be warned that it's not smart enough to filter out alpha/beta/RC versions. If that's a problem, you might want to use GitLab branches instead. +- **Stable branch** -4. **Tags** (this is the default option): - - To release version 1.2.3, create a new Git tag named `v1.2.3` or `1.2.3`. - - Optionally, add the following code: - ```php - //Add the following code to your main plugin file or `functions.php` file to check for updates from the default branch - $myUpdateChecker->setBranch('master'); //or 'main' - ``` - - PUC doesn't require strict adherence to [SemVer](http://semver.org/). These are all valid tag names: `v1.2.3`, `v1.2-foo`, `1.2.3_rc1-ABC`, `1.2.3.4.5`. However, be warned that it's not smart enough to filter out alpha/beta/RC versions. If that's a problem, you might want to use GitLab branches instead. + Point the update checker at any stable, production-ready branch: + ```php + $myUpdateChecker->setBranch('stable-branch-name'); + ``` + PUC will periodically check the `Version` header in the main plugin file or `style.css` and display a notification if it's greater than the installed version. Caveat: Even if you set the branch to `main` (the default) or `master` (the historical default), the update checker will still look for recent releases and tags first. + +Migrating from 4.x +------------------ + +Older versions of the library didn't use namespaces. Code that was written for those versions will need to be updated to work with the current version. At a minimum, you'll need to change the factory class name. + +Old code: +```php +$myUpdateChecker = Puc_v4_Factory::buildUpdateChecker( + 'https://example.com/info.json', + __FILE__, + 'my-slug' +); +``` + +New code: +```php +use YahnisElsts\PluginUpdateChecker\v5\PucFactory; + +$myUpdateChecker = PucFactory::buildUpdateChecker( + 'https://example.com/info.json', + __FILE__, + 'my-slug' +); +``` + +Other classes have also been renamed, usually by simply removing the `Puc_vXpY_` prefix and converting `Category_Thing` to `Category\Thing`. Here's a table of the most commonly used classes and their new names: + +| Old class name | New class name | +|-------------------------------------|----------------------------------------------------------------| +| `Puc_v4_Factory` | `YahnisElsts\PluginUpdateChecker\v5\PucFactory` | +| `Puc_v4p13_Factory` | `YahnisElsts\PluginUpdateChecker\v5p1\PucFactory` | +| `Puc_v4p13_Plugin_UpdateChecker` | `YahnisElsts\PluginUpdateChecker\v5p1\Plugin\UpdateChecker` | +| `Puc_v4p13_Theme_UpdateChecker` | `YahnisElsts\PluginUpdateChecker\v5p1\Theme\UpdateChecker` | +| `Puc_v4p13_Vcs_PluginUpdateChecker` | `YahnisElsts\PluginUpdateChecker\v5p1\Vcs\PluginUpdateChecker` | +| `Puc_v4p13_Vcs_ThemeUpdateChecker` | `YahnisElsts\PluginUpdateChecker\v5p1\Vcs\ThemeUpdateChecker` | +| `Puc_v4p13_Vcs_GitHubApi` | `YahnisElsts\PluginUpdateChecker\v5p1\Vcs\GitHubApi` | +| `Puc_v4p13_Vcs_GitLabApi` | `YahnisElsts\PluginUpdateChecker\v5p1\Vcs\GitLabApi` | +| `Puc_v4p13_Vcs_BitBucketApi` | `YahnisElsts\PluginUpdateChecker\v5p1\Vcs\BitBucketApi` | License Management ------------------ @@ -318,9 +364,9 @@ Currently, the update checker doesn't have any built-in license management featu Resources --------- -- [This blog post](http://w-shadow.com/blog/2010/09/02/automatic-updates-for-any-plugin/) has more information about the update checker API. *Slightly out of date.* +- [This blog post](https://w-shadow.com/blog/2010/09/02/automatic-updates-for-any-plugin/) has more information about the update checker API. *Slightly out of date.* - [Debug Bar](https://wordpress.org/plugins/debug-bar/) - useful for testing and debugging the update checker. - [Update format reference](https://docs.google.com/spreadsheets/d/1eOBbW7Go2qEQXReOOCdidMTf_tDYRq4JfegcO1CBPIs/edit?usp=sharing) - describes all fields supported by the JSON-based update information format used by the update checker. Only covers plugins. Themes use a similar but more limited format. -- [Securing download links](http://w-shadow.com/blog/2013/03/19/plugin-updates-securing-download-links/) - a general overview. -- [A GUI for entering download credentials](http://open-tools.net/documentation/tutorial-automatic-updates.html#wordpress) -- [Theme Update Checker](http://w-shadow.com/blog/2011/06/02/automatic-updates-for-commercial-themes/) - an older, theme-only variant of this update checker. +- [Securing download links](https://w-shadow.com/blog/2013/03/19/plugin-updates-securing-download-links/) - a general overview. +- [A GUI for entering download credentials](https://open-tools.net/documentation/tutorial-automatic-updates.html#wordpress) +- [Theme Update Checker](https://w-shadow.com/blog/2011/06/02/automatic-updates-for-commercial-themes/) - an older, theme-only variant of this update checker. diff --git a/vendor/yahnis-elsts/plugin-update-checker/composer.json b/vendor/yahnis-elsts/plugin-update-checker/composer.json index 7f97a49bd..1a71ce838 100644 --- a/vendor/yahnis-elsts/plugin-update-checker/composer.json +++ b/vendor/yahnis-elsts/plugin-update-checker/composer.json @@ -9,15 +9,15 @@ { "name": "Yahnis Elsts", "email": "whiteshadow@w-shadow.com", - "homepage": "http://w-shadow.com/", + "homepage": "https://w-shadow.com/", "role": "Developer" } ], "require": { - "php": ">=5.2.0", + "php": ">=5.6.20", "ext-json": "*" }, "autoload": { - "files": ["load-v4p13.php"] + "files": ["load-v5p1.php"] } } diff --git a/vendor/yahnis-elsts/plugin-update-checker/css/puc-debug-bar.css b/vendor/yahnis-elsts/plugin-update-checker/css/puc-debug-bar.css index 2cb3f8e69..649db4fa1 100644 --- a/vendor/yahnis-elsts/plugin-update-checker/css/puc-debug-bar.css +++ b/vendor/yahnis-elsts/plugin-update-checker/css/puc-debug-bar.css @@ -1,4 +1,4 @@ -.puc-debug-bar-panel-v4 pre { +.puc-debug-bar-panel-v5 pre { margin-top: 0; } diff --git a/vendor/yahnis-elsts/plugin-update-checker/examples/plugin.json b/vendor/yahnis-elsts/plugin-update-checker/examples/plugin.json index fea211a12..946b73076 100644 --- a/vendor/yahnis-elsts/plugin-update-checker/examples/plugin.json +++ b/vendor/yahnis-elsts/plugin-update-checker/examples/plugin.json @@ -1,52 +1,52 @@ -{ - "name": "My Example Plugin", - "version": "2.0", - "download_url": "http://example.com/updates/example-plugin.zip", - - "homepage": "http://example.com/", - "requires": "4.5", - "tested": "4.8", - "last_updated": "2017-01-01 16:17:00", - "upgrade_notice": "Here's why you should upgrade...", - - "author": "Janis Elsts", - "author_homepage": "http://example.com/", - - "sections": { - "description": "(Required) Plugin description. Basic HTML can be used in all sections.", - "installation": "(Recommended) Installation instructions.", - "changelog": "(Recommended) Changelog.

This section will be displayed by default when the user clicks 'View version x.y.z details'.

", - "custom_section": "This is a custom section labeled 'Custom Section'." - }, - - "icons" : { - "1x" : "http://w-shadow.com/files/external-update-example/assets/icon-128x128.png", - "2x" : "http://w-shadow.com/files/external-update-example/assets/icon-256x256.png" - }, - - "banners": { - "low": "http://w-shadow.com/files/external-update-example/assets/banner-772x250.png", - "high": "http://w-shadow.com/files/external-update-example/assets/banner-1544x500.png" - }, - - "translations": [ - { - "language": "fr_FR", - "version": "4.0", - "updated": "2016-04-22 23:22:42", - "package": "http://example.com/updates/translations/french-language-pack.zip" - }, - { - "language": "de_DE", - "version": "5.0", - "updated": "2016-04-22 23:22:42", - "package": "http://example.com/updates/translations/german-language-pack.zip" - } - ], - - "rating": 90, - "num_ratings": 123, - - "downloaded": 1234, - "active_installs": 12345 +{ + "name": "My Example Plugin", + "version": "2.0", + "download_url": "http://example.com/updates/example-plugin.zip", + + "homepage": "http://example.com/", + "requires": "4.5", + "tested": "4.8", + "last_updated": "2017-01-01 16:17:00", + "upgrade_notice": "Here's why you should upgrade...", + + "author": "Janis Elsts", + "author_homepage": "http://example.com/", + + "sections": { + "description": "(Required) Plugin description. Basic HTML can be used in all sections.", + "installation": "(Recommended) Installation instructions.", + "changelog": "(Recommended) Changelog.

This section will be displayed by default when the user clicks 'View version x.y.z details'.

", + "custom_section": "This is a custom section labeled 'Custom Section'." + }, + + "icons" : { + "1x" : "http://w-shadow.com/files/external-update-example/assets/icon-128x128.png", + "2x" : "http://w-shadow.com/files/external-update-example/assets/icon-256x256.png" + }, + + "banners": { + "low": "http://w-shadow.com/files/external-update-example/assets/banner-772x250.png", + "high": "http://w-shadow.com/files/external-update-example/assets/banner-1544x500.png" + }, + + "translations": [ + { + "language": "fr_FR", + "version": "4.0", + "updated": "2016-04-22 23:22:42", + "package": "http://example.com/updates/translations/french-language-pack.zip" + }, + { + "language": "de_DE", + "version": "5.0", + "updated": "2016-04-22 23:22:42", + "package": "http://example.com/updates/translations/german-language-pack.zip" + } + ], + + "rating": 90, + "num_ratings": 123, + + "downloaded": 1234, + "active_installs": 12345 } \ No newline at end of file diff --git a/vendor/yahnis-elsts/plugin-update-checker/examples/theme.json b/vendor/yahnis-elsts/plugin-update-checker/examples/theme.json index df6c8c797..0e080725f 100644 --- a/vendor/yahnis-elsts/plugin-update-checker/examples/theme.json +++ b/vendor/yahnis-elsts/plugin-update-checker/examples/theme.json @@ -1,5 +1,5 @@ -{ - "version": "2.0", - "details_url": "http://example.com/version-2.0-details.html", - "download_url": "http://example.com/example-theme-2.0.zip" +{ + "version": "2.0", + "details_url": "http://example.com/version-2.0-details.html", + "download_url": "http://example.com/example-theme-2.0.zip" } \ No newline at end of file diff --git a/vendor/yahnis-elsts/plugin-update-checker/js/debug-bar.js b/vendor/yahnis-elsts/plugin-update-checker/js/debug-bar.js index 2452c0204..80f53f11e 100644 --- a/vendor/yahnis-elsts/plugin-update-checker/js/debug-bar.js +++ b/vendor/yahnis-elsts/plugin-update-checker/js/debug-bar.js @@ -2,7 +2,7 @@ jQuery(function($) { function runAjaxAction(button, action) { button = $(button); - var panel = button.closest('.puc-debug-bar-panel-v4'); + var panel = button.closest('.puc-debug-bar-panel-v5'); var responseBox = button.closest('td').find('.puc-ajax-response'); responseBox.text('Processing...').show(); @@ -14,19 +14,21 @@ jQuery(function($) { _wpnonce: panel.data('nonce') }, function(data) { + //The response contains HTML that should already be escaped in server-side code. + //phpcs:ignore WordPressVIPMinimum.JS.HTMLExecutingFunctions.html responseBox.html(data); }, 'html' ); } - $('.puc-debug-bar-panel-v4 input[name="puc-check-now-button"]').on('click', function() { - runAjaxAction(this, 'puc_v4_debug_check_now'); + $('.puc-debug-bar-panel-v5 input[name="puc-check-now-button"]').on('click', function() { + runAjaxAction(this, 'puc_v5_debug_check_now'); return false; }); - $('.puc-debug-bar-panel-v4 input[name="puc-request-info-button"]').on('click', function() { - runAjaxAction(this, 'puc_v4_debug_request_info'); + $('.puc-debug-bar-panel-v5 input[name="puc-request-info-button"]').on('click', function() { + runAjaxAction(this, 'puc_v5_debug_request_info'); return false; }); @@ -34,7 +36,7 @@ jQuery(function($) { // Debug Bar uses the panel class name as part of its link and container IDs. This means we can // end up with multiple identical IDs if more than one plugin uses the update checker library. // Fix it by replacing the class name with the plugin slug. - var panels = $('#debug-menu-targets').find('.puc-debug-bar-panel-v4'); + var panels = $('#debug-menu-targets').find('.puc-debug-bar-panel-v5'); panels.each(function() { var panel = $(this); var uid = panel.data('uid'); diff --git a/vendor/yahnis-elsts/plugin-update-checker/languages/plugin-update-checker-cs_CZ.po b/vendor/yahnis-elsts/plugin-update-checker/languages/plugin-update-checker-cs_CZ.po index 2c9af18f9..a47c5e5c4 100644 --- a/vendor/yahnis-elsts/plugin-update-checker/languages/plugin-update-checker-cs_CZ.po +++ b/vendor/yahnis-elsts/plugin-update-checker/languages/plugin-update-checker-cs_CZ.po @@ -1,45 +1,45 @@ -msgid "" -msgstr "" -"Project-Id-Version: plugin-update-checker\n" -"Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2017-05-20 10:53+0300\n" -"PO-Revision-Date: 2017-07-05 15:39+0000\n" -"Last-Translator: Vojtěch Sajdl \n" -"Language-Team: Czech (Czech Republic)\n" -"Language: cs-CZ\n" -"Plural-Forms: nplurals=2; plural=(n != 1)\n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"X-Loco-Source-Locale: cs_CZ\n" -"X-Generator: Loco - https://localise.biz/\n" -"X-Poedit-Basepath: ..\n" -"X-Poedit-SourceCharset: UTF-8\n" -"X-Poedit-KeywordsList: __;_e;_x:1,2c;_x\n" -"X-Poedit-SearchPath-0: .\n" -"X-Loco-Parser: loco_parse_po" - -#: Puc/v4p1/Plugin/UpdateChecker.php:358 -msgid "Check for updates" -msgstr "Zkontrolovat aktualizace" - -#: Puc/v4p1/Plugin/UpdateChecker.php:405 -#, php-format -msgctxt "the plugin title" -msgid "The %s plugin is up to date." -msgstr "Plugin %s je aktuální." - -#: Puc/v4p1/Plugin/UpdateChecker.php:407 -#, php-format -msgctxt "the plugin title" -msgid "A new version of the %s plugin is available." -msgstr "Nová verze pluginu %s je dostupná." - -#: Puc/v4p1/Plugin/UpdateChecker.php:409 -#, php-format -msgid "Unknown update checker status \"%s\"" -msgstr "Neznámý status kontroly aktualizací \"%s\"" - -#: Puc/v4p1/Vcs/PluginUpdateChecker.php:83 -msgid "There is no changelog available." -msgstr "Changelog není dostupný." +msgid "" +msgstr "" +"Project-Id-Version: plugin-update-checker\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2017-05-20 10:53+0300\n" +"PO-Revision-Date: 2017-07-05 15:39+0000\n" +"Last-Translator: Vojtěch Sajdl \n" +"Language-Team: Czech (Czech Republic)\n" +"Language: cs-CZ\n" +"Plural-Forms: nplurals=2; plural=(n != 1)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"X-Loco-Source-Locale: cs_CZ\n" +"X-Generator: Loco - https://localise.biz/\n" +"X-Poedit-Basepath: ..\n" +"X-Poedit-SourceCharset: UTF-8\n" +"X-Poedit-KeywordsList: __;_e;_x:1,2c;_x\n" +"X-Poedit-SearchPath-0: .\n" +"X-Loco-Parser: loco_parse_po" + +#: Puc/v4p1/Plugin/UpdateChecker.php:358 +msgid "Check for updates" +msgstr "Zkontrolovat aktualizace" + +#: Puc/v4p1/Plugin/UpdateChecker.php:405 +#, php-format +msgctxt "the plugin title" +msgid "The %s plugin is up to date." +msgstr "Plugin %s je aktuální." + +#: Puc/v4p1/Plugin/UpdateChecker.php:407 +#, php-format +msgctxt "the plugin title" +msgid "A new version of the %s plugin is available." +msgstr "Nová verze pluginu %s je dostupná." + +#: Puc/v4p1/Plugin/UpdateChecker.php:409 +#, php-format +msgid "Unknown update checker status \"%s\"" +msgstr "Neznámý status kontroly aktualizací \"%s\"" + +#: Puc/v4p1/Vcs/PluginUpdateChecker.php:83 +msgid "There is no changelog available." +msgstr "Changelog není dostupný." diff --git a/vendor/yahnis-elsts/plugin-update-checker/languages/plugin-update-checker.pot b/vendor/yahnis-elsts/plugin-update-checker/languages/plugin-update-checker.pot index 127a4893c..edc8de4f2 100644 --- a/vendor/yahnis-elsts/plugin-update-checker/languages/plugin-update-checker.pot +++ b/vendor/yahnis-elsts/plugin-update-checker/languages/plugin-update-checker.pot @@ -17,33 +17,33 @@ msgstr "" "X-Poedit-KeywordsList: __;_e;_x:1,2c;_x\n" "X-Poedit-SearchPath-0: .\n" -#: Puc/v4p13/Plugin/Ui.php:128 +#: Puc/v5p1/Plugin/Ui.php:128 msgid "Check for updates" msgstr "" -#: Puc/v4p13/Plugin/Ui.php:214 +#: Puc/v5p1/Plugin/Ui.php:214 #, php-format msgctxt "the plugin title" msgid "The %s plugin is up to date." msgstr "" -#: Puc/v4p13/Plugin/Ui.php:216 +#: Puc/v5p1/Plugin/Ui.php:216 #, php-format msgctxt "the plugin title" msgid "A new version of the %s plugin is available." msgstr "" -#: Puc/v4p13/Plugin/Ui.php:218 +#: Puc/v5p1/Plugin/Ui.php:218 #, php-format msgctxt "the plugin title" msgid "Could not determine if updates are available for %s." msgstr "" -#: Puc/v4p13/Plugin/Ui.php:224 +#: Puc/v5p1/Plugin/Ui.php:224 #, php-format msgid "Unknown update checker status \"%s\"" msgstr "" -#: Puc/v4p13/Vcs/PluginUpdateChecker.php:100 +#: Puc/v5p1/Vcs/PluginUpdateChecker.php:100 msgid "There is no changelog available." msgstr "" diff --git a/vendor/yahnis-elsts/plugin-update-checker/load-v4p13.php b/vendor/yahnis-elsts/plugin-update-checker/load-v4p13.php deleted file mode 100644 index 8b67c1a29..000000000 --- a/vendor/yahnis-elsts/plugin-update-checker/load-v4p13.php +++ /dev/null @@ -1,28 +0,0 @@ - 'Puc_v4p13_Plugin_UpdateChecker', - 'Theme_UpdateChecker' => 'Puc_v4p13_Theme_UpdateChecker', - - 'Vcs_PluginUpdateChecker' => 'Puc_v4p13_Vcs_PluginUpdateChecker', - 'Vcs_ThemeUpdateChecker' => 'Puc_v4p13_Vcs_ThemeUpdateChecker', - - 'GitHubApi' => 'Puc_v4p13_Vcs_GitHubApi', - 'BitBucketApi' => 'Puc_v4p13_Vcs_BitBucketApi', - 'GitLabApi' => 'Puc_v4p13_Vcs_GitLabApi', - ) - as $pucGeneralClass => $pucVersionedClass -) { - Puc_v4_Factory::addVersion($pucGeneralClass, $pucVersionedClass, '4.13'); - //Also add it to the minor-version factory in case the major-version factory - //was already defined by another, older version of the update checker. - Puc_v4p13_Factory::addVersion($pucGeneralClass, $pucVersionedClass, '4.13'); -} - diff --git a/vendor/yahnis-elsts/plugin-update-checker/load-v5p1.php b/vendor/yahnis-elsts/plugin-update-checker/load-v5p1.php new file mode 100644 index 000000000..83cebcb65 --- /dev/null +++ b/vendor/yahnis-elsts/plugin-update-checker/load-v5p1.php @@ -0,0 +1,34 @@ + Plugin\UpdateChecker::class, + 'Theme\\UpdateChecker' => Theme\UpdateChecker::class, + + 'Vcs\\PluginUpdateChecker' => Vcs\PluginUpdateChecker::class, + 'Vcs\\ThemeUpdateChecker' => Vcs\ThemeUpdateChecker::class, + + 'GitHubApi' => Vcs\GitHubApi::class, + 'BitBucketApi' => Vcs\BitBucketApi::class, + 'GitLabApi' => Vcs\GitLabApi::class, + ) + as $pucGeneralClass => $pucVersionedClass +) { + MajorFactory::addVersion($pucGeneralClass, $pucVersionedClass, '5.1'); + //Also add it to the minor-version factory in case the major-version factory + //was already defined by another, older version of the update checker. + MinorFactory::addVersion($pucGeneralClass, $pucVersionedClass, '5.1'); +} + diff --git a/vendor/yahnis-elsts/plugin-update-checker/phpcs.xml b/vendor/yahnis-elsts/plugin-update-checker/phpcs.xml new file mode 100644 index 000000000..a8fe14813 --- /dev/null +++ b/vendor/yahnis-elsts/plugin-update-checker/phpcs.xml @@ -0,0 +1,21 @@ + + + PHPCS settings for Plugin Update Checker + + + + + + + + ./ + + + + + + + + + ^vendor/* + diff --git a/vendor/yahnis-elsts/plugin-update-checker/plugin-update-checker.php b/vendor/yahnis-elsts/plugin-update-checker/plugin-update-checker.php index da4348f97..ebf10bc75 100644 --- a/vendor/yahnis-elsts/plugin-update-checker/plugin-update-checker.php +++ b/vendor/yahnis-elsts/plugin-update-checker/plugin-update-checker.php @@ -1,10 +1,10 @@ =') ) { - require __DIR__ . '/ParsedownModern.php'; - } else { - require __DIR__ . '/ParsedownLegacy.php'; - } + require __DIR__ . '/ParsedownModern.php'; } diff --git a/vendor/yahnis-elsts/plugin-update-checker/vendor/ParsedownLegacy.php b/vendor/yahnis-elsts/plugin-update-checker/vendor/ParsedownLegacy.php deleted file mode 100644 index bbc2d3236..000000000 --- a/vendor/yahnis-elsts/plugin-update-checker/vendor/ParsedownLegacy.php +++ /dev/null @@ -1,1535 +0,0 @@ -DefinitionData = array(); - - # standardize line breaks - $text = str_replace(array("\r\n", "\r"), "\n", $text); - - # remove surrounding line breaks - $text = trim($text, "\n"); - - # split text into lines - $lines = explode("\n", $text); - - # iterate through lines to identify blocks - $markup = $this->lines($lines); - - # trim line breaks - $markup = trim($markup, "\n"); - - return $markup; - } - - # - # Setters - # - - function setBreaksEnabled($breaksEnabled) - { - $this->breaksEnabled = $breaksEnabled; - - return $this; - } - - protected $breaksEnabled; - - function setMarkupEscaped($markupEscaped) - { - $this->markupEscaped = $markupEscaped; - - return $this; - } - - protected $markupEscaped; - - function setUrlsLinked($urlsLinked) - { - $this->urlsLinked = $urlsLinked; - - return $this; - } - - protected $urlsLinked = true; - - # - # Lines - # - - protected $BlockTypes = array( - '#' => array('Header'), - '*' => array('Rule', 'List'), - '+' => array('List'), - '-' => array('SetextHeader', 'Table', 'Rule', 'List'), - '0' => array('List'), - '1' => array('List'), - '2' => array('List'), - '3' => array('List'), - '4' => array('List'), - '5' => array('List'), - '6' => array('List'), - '7' => array('List'), - '8' => array('List'), - '9' => array('List'), - ':' => array('Table'), - '<' => array('Comment', 'Markup'), - '=' => array('SetextHeader'), - '>' => array('Quote'), - '[' => array('Reference'), - '_' => array('Rule'), - '`' => array('FencedCode'), - '|' => array('Table'), - '~' => array('FencedCode'), - ); - - # ~ - - protected $DefinitionTypes = array( - '[' => array('Reference'), - ); - - # ~ - - protected $unmarkedBlockTypes = array( - 'Code', - ); - - # - # Blocks - # - - private function lines(array $lines) - { - $CurrentBlock = null; - - foreach ($lines as $line) - { - if (chop($line) === '') - { - if (isset($CurrentBlock)) - { - $CurrentBlock['interrupted'] = true; - } - - continue; - } - - if (strpos($line, "\t") !== false) - { - $parts = explode("\t", $line); - - $line = $parts[0]; - - unset($parts[0]); - - foreach ($parts as $part) - { - $shortage = 4 - mb_strlen($line, 'utf-8') % 4; - - $line .= str_repeat(' ', $shortage); - $line .= $part; - } - } - - $indent = 0; - - while (isset($line[$indent]) and $line[$indent] === ' ') - { - $indent ++; - } - - $text = $indent > 0 ? substr($line, $indent) : $line; - - # ~ - - $Line = array('body' => $line, 'indent' => $indent, 'text' => $text); - - # ~ - - if (isset($CurrentBlock['incomplete'])) - { - $Block = $this->{'block'.$CurrentBlock['type'].'Continue'}($Line, $CurrentBlock); - - if (isset($Block)) - { - $CurrentBlock = $Block; - - continue; - } - else - { - if (method_exists($this, 'block'.$CurrentBlock['type'].'Complete')) - { - $CurrentBlock = $this->{'block'.$CurrentBlock['type'].'Complete'}($CurrentBlock); - } - - unset($CurrentBlock['incomplete']); - } - } - - # ~ - - $marker = $text[0]; - - # ~ - - $blockTypes = $this->unmarkedBlockTypes; - - if (isset($this->BlockTypes[$marker])) - { - foreach ($this->BlockTypes[$marker] as $blockType) - { - $blockTypes []= $blockType; - } - } - - # - # ~ - - foreach ($blockTypes as $blockType) - { - $Block = $this->{'block'.$blockType}($Line, $CurrentBlock); - - if (isset($Block)) - { - $Block['type'] = $blockType; - - if ( ! isset($Block['identified'])) - { - $Blocks []= $CurrentBlock; - - $Block['identified'] = true; - } - - if (method_exists($this, 'block'.$blockType.'Continue')) - { - $Block['incomplete'] = true; - } - - $CurrentBlock = $Block; - - continue 2; - } - } - - # ~ - - if (isset($CurrentBlock) and ! isset($CurrentBlock['type']) and ! isset($CurrentBlock['interrupted'])) - { - $CurrentBlock['element']['text'] .= "\n".$text; - } - else - { - $Blocks []= $CurrentBlock; - - $CurrentBlock = $this->paragraph($Line); - - $CurrentBlock['identified'] = true; - } - } - - # ~ - - if (isset($CurrentBlock['incomplete']) and method_exists($this, 'block'.$CurrentBlock['type'].'Complete')) - { - $CurrentBlock = $this->{'block'.$CurrentBlock['type'].'Complete'}($CurrentBlock); - } - - # ~ - - $Blocks []= $CurrentBlock; - - unset($Blocks[0]); - - # ~ - - $markup = ''; - - foreach ($Blocks as $Block) - { - if (isset($Block['hidden'])) - { - continue; - } - - $markup .= "\n"; - $markup .= isset($Block['markup']) ? $Block['markup'] : $this->element($Block['element']); - } - - $markup .= "\n"; - - # ~ - - return $markup; - } - - # - # Code - - protected function blockCode($Line, $Block = null) - { - if (isset($Block) and ! isset($Block['type']) and ! isset($Block['interrupted'])) - { - return; - } - - if ($Line['indent'] >= 4) - { - $text = substr($Line['body'], 4); - - $Block = array( - 'element' => array( - 'name' => 'pre', - 'handler' => 'element', - 'text' => array( - 'name' => 'code', - 'text' => $text, - ), - ), - ); - - return $Block; - } - } - - protected function blockCodeContinue($Line, $Block) - { - if ($Line['indent'] >= 4) - { - if (isset($Block['interrupted'])) - { - $Block['element']['text']['text'] .= "\n"; - - unset($Block['interrupted']); - } - - $Block['element']['text']['text'] .= "\n"; - - $text = substr($Line['body'], 4); - - $Block['element']['text']['text'] .= $text; - - return $Block; - } - } - - protected function blockCodeComplete($Block) - { - $text = $Block['element']['text']['text']; - - $text = htmlspecialchars($text, ENT_NOQUOTES, 'UTF-8'); - - $Block['element']['text']['text'] = $text; - - return $Block; - } - - # - # Comment - - protected function blockComment($Line) - { - if ($this->markupEscaped) - { - return; - } - - if (isset($Line['text'][3]) and $Line['text'][3] === '-' and $Line['text'][2] === '-' and $Line['text'][1] === '!') - { - $Block = array( - 'markup' => $Line['body'], - ); - - if (preg_match('/-->$/', $Line['text'])) - { - $Block['closed'] = true; - } - - return $Block; - } - } - - protected function blockCommentContinue($Line, array $Block) - { - if (isset($Block['closed'])) - { - return; - } - - $Block['markup'] .= "\n" . $Line['body']; - - if (preg_match('/-->$/', $Line['text'])) - { - $Block['closed'] = true; - } - - return $Block; - } - - # - # Fenced Code - - protected function blockFencedCode($Line) - { - if (preg_match('/^(['.$Line['text'][0].']{3,})[ ]*([\w-]+)?[ ]*$/', $Line['text'], $matches)) - { - $Element = array( - 'name' => 'code', - 'text' => '', - ); - - if (isset($matches[2])) - { - $class = 'language-'.$matches[2]; - - $Element['attributes'] = array( - 'class' => $class, - ); - } - - $Block = array( - 'char' => $Line['text'][0], - 'element' => array( - 'name' => 'pre', - 'handler' => 'element', - 'text' => $Element, - ), - ); - - return $Block; - } - } - - protected function blockFencedCodeContinue($Line, $Block) - { - if (isset($Block['complete'])) - { - return; - } - - if (isset($Block['interrupted'])) - { - $Block['element']['text']['text'] .= "\n"; - - unset($Block['interrupted']); - } - - if (preg_match('/^'.$Block['char'].'{3,}[ ]*$/', $Line['text'])) - { - $Block['element']['text']['text'] = substr($Block['element']['text']['text'], 1); - - $Block['complete'] = true; - - return $Block; - } - - $Block['element']['text']['text'] .= "\n".$Line['body'];; - - return $Block; - } - - protected function blockFencedCodeComplete($Block) - { - $text = $Block['element']['text']['text']; - - $text = htmlspecialchars($text, ENT_NOQUOTES, 'UTF-8'); - - $Block['element']['text']['text'] = $text; - - return $Block; - } - - # - # Header - - protected function blockHeader($Line) - { - if (isset($Line['text'][1])) - { - $level = 1; - - while (isset($Line['text'][$level]) and $Line['text'][$level] === '#') - { - $level ++; - } - - if ($level > 6) - { - return; - } - - $text = trim($Line['text'], '# '); - - $Block = array( - 'element' => array( - 'name' => 'h' . min(6, $level), - 'text' => $text, - 'handler' => 'line', - ), - ); - - return $Block; - } - } - - # - # List - - protected function blockList($Line) - { - list($name, $pattern) = $Line['text'][0] <= '-' ? array('ul', '[*+-]') : array('ol', '[0-9]+[.]'); - - if (preg_match('/^('.$pattern.'[ ]+)(.*)/', $Line['text'], $matches)) - { - $Block = array( - 'indent' => $Line['indent'], - 'pattern' => $pattern, - 'element' => array( - 'name' => $name, - 'handler' => 'elements', - ), - ); - - $Block['li'] = array( - 'name' => 'li', - 'handler' => 'li', - 'text' => array( - $matches[2], - ), - ); - - $Block['element']['text'] []= & $Block['li']; - - return $Block; - } - } - - protected function blockListContinue($Line, array $Block) - { - if ($Block['indent'] === $Line['indent'] and preg_match('/^'.$Block['pattern'].'(?:[ ]+(.*)|$)/', $Line['text'], $matches)) - { - if (isset($Block['interrupted'])) - { - $Block['li']['text'] []= ''; - - unset($Block['interrupted']); - } - - unset($Block['li']); - - $text = isset($matches[1]) ? $matches[1] : ''; - - $Block['li'] = array( - 'name' => 'li', - 'handler' => 'li', - 'text' => array( - $text, - ), - ); - - $Block['element']['text'] []= & $Block['li']; - - return $Block; - } - - if ($Line['text'][0] === '[' and $this->blockReference($Line)) - { - return $Block; - } - - if ( ! isset($Block['interrupted'])) - { - $text = preg_replace('/^[ ]{0,4}/', '', $Line['body']); - - $Block['li']['text'] []= $text; - - return $Block; - } - - if ($Line['indent'] > 0) - { - $Block['li']['text'] []= ''; - - $text = preg_replace('/^[ ]{0,4}/', '', $Line['body']); - - $Block['li']['text'] []= $text; - - unset($Block['interrupted']); - - return $Block; - } - } - - # - # Quote - - protected function blockQuote($Line) - { - if (preg_match('/^>[ ]?(.*)/', $Line['text'], $matches)) - { - $Block = array( - 'element' => array( - 'name' => 'blockquote', - 'handler' => 'lines', - 'text' => (array) $matches[1], - ), - ); - - return $Block; - } - } - - protected function blockQuoteContinue($Line, array $Block) - { - if ($Line['text'][0] === '>' and preg_match('/^>[ ]?(.*)/', $Line['text'], $matches)) - { - if (isset($Block['interrupted'])) - { - $Block['element']['text'] []= ''; - - unset($Block['interrupted']); - } - - $Block['element']['text'] []= $matches[1]; - - return $Block; - } - - if ( ! isset($Block['interrupted'])) - { - $Block['element']['text'] []= $Line['text']; - - return $Block; - } - } - - # - # Rule - - protected function blockRule($Line) - { - if (preg_match('/^(['.$Line['text'][0].'])([ ]*\1){2,}[ ]*$/', $Line['text'])) - { - $Block = array( - 'element' => array( - 'name' => 'hr' - ), - ); - - return $Block; - } - } - - # - # Setext - - protected function blockSetextHeader($Line, array $Block = null) - { - if ( ! isset($Block) or isset($Block['type']) or isset($Block['interrupted'])) - { - return; - } - - if (chop($Line['text'], $Line['text'][0]) === '') - { - $Block['element']['name'] = $Line['text'][0] === '=' ? 'h1' : 'h2'; - - return $Block; - } - } - - # - # Markup - - protected function blockMarkup($Line) - { - if ($this->markupEscaped) - { - return; - } - - if (preg_match('/^<(\w*)(?:[ ]*'.$this->regexHtmlAttribute.')*[ ]*(\/)?>/', $Line['text'], $matches)) - { - if (in_array($matches[1], $this->textLevelElements)) - { - return; - } - - $Block = array( - 'name' => $matches[1], - 'depth' => 0, - 'markup' => $Line['text'], - ); - - $length = strlen($matches[0]); - - $remainder = substr($Line['text'], $length); - - if (trim($remainder) === '') - { - if (isset($matches[2]) or in_array($matches[1], $this->voidElements)) - { - $Block['closed'] = true; - - $Block['void'] = true; - } - } - else - { - if (isset($matches[2]) or in_array($matches[1], $this->voidElements)) - { - return; - } - - if (preg_match('/<\/'.$matches[1].'>[ ]*$/i', $remainder)) - { - $Block['closed'] = true; - } - } - - return $Block; - } - } - - protected function blockMarkupContinue($Line, array $Block) - { - if (isset($Block['closed'])) - { - return; - } - - if (preg_match('/^<'.$Block['name'].'(?:[ ]*'.$this->regexHtmlAttribute.')*[ ]*>/i', $Line['text'])) # open - { - $Block['depth'] ++; - } - - if (preg_match('/(.*?)<\/'.$Block['name'].'>[ ]*$/i', $Line['text'], $matches)) # close - { - if ($Block['depth'] > 0) - { - $Block['depth'] --; - } - else - { - $Block['closed'] = true; - } - - $Block['markup'] .= $matches[1]; - } - - if (isset($Block['interrupted'])) - { - $Block['markup'] .= "\n"; - - unset($Block['interrupted']); - } - - $Block['markup'] .= "\n".$Line['body']; - - return $Block; - } - - # - # Reference - - protected function blockReference($Line) - { - if (preg_match('/^\[(.+?)\]:[ ]*?(?:[ ]+["\'(](.+)["\')])?[ ]*$/', $Line['text'], $matches)) - { - $id = strtolower($matches[1]); - - $Data = array( - 'url' => $matches[2], - 'title' => null, - ); - - if (isset($matches[3])) - { - $Data['title'] = $matches[3]; - } - - $this->DefinitionData['Reference'][$id] = $Data; - - $Block = array( - 'hidden' => true, - ); - - return $Block; - } - } - - # - # Table - - protected function blockTable($Line, array $Block = null) - { - if ( ! isset($Block) or isset($Block['type']) or isset($Block['interrupted'])) - { - return; - } - - if (strpos($Block['element']['text'], '|') !== false and chop($Line['text'], ' -:|') === '') - { - $alignments = array(); - - $divider = $Line['text']; - - $divider = trim($divider); - $divider = trim($divider, '|'); - - $dividerCells = explode('|', $divider); - - foreach ($dividerCells as $dividerCell) - { - $dividerCell = trim($dividerCell); - - if ($dividerCell === '') - { - continue; - } - - $alignment = null; - - if ($dividerCell[0] === ':') - { - $alignment = 'left'; - } - - if (substr($dividerCell, - 1) === ':') - { - $alignment = $alignment === 'left' ? 'center' : 'right'; - } - - $alignments []= $alignment; - } - - # ~ - - $HeaderElements = array(); - - $header = $Block['element']['text']; - - $header = trim($header); - $header = trim($header, '|'); - - $headerCells = explode('|', $header); - - foreach ($headerCells as $index => $headerCell) - { - $headerCell = trim($headerCell); - - $HeaderElement = array( - 'name' => 'th', - 'text' => $headerCell, - 'handler' => 'line', - ); - - if (isset($alignments[$index])) - { - $alignment = $alignments[$index]; - - $HeaderElement['attributes'] = array( - 'style' => 'text-align: '.$alignment.';', - ); - } - - $HeaderElements []= $HeaderElement; - } - - # ~ - - $Block = array( - 'alignments' => $alignments, - 'identified' => true, - 'element' => array( - 'name' => 'table', - 'handler' => 'elements', - ), - ); - - $Block['element']['text'] []= array( - 'name' => 'thead', - 'handler' => 'elements', - ); - - $Block['element']['text'] []= array( - 'name' => 'tbody', - 'handler' => 'elements', - 'text' => array(), - ); - - $Block['element']['text'][0]['text'] []= array( - 'name' => 'tr', - 'handler' => 'elements', - 'text' => $HeaderElements, - ); - - return $Block; - } - } - - protected function blockTableContinue($Line, array $Block) - { - if (isset($Block['interrupted'])) - { - return; - } - - if ($Line['text'][0] === '|' or strpos($Line['text'], '|')) - { - $Elements = array(); - - $row = $Line['text']; - - $row = trim($row); - $row = trim($row, '|'); - - preg_match_all('/(?:(\\\\[|])|[^|`]|`[^`]+`|`)+/', $row, $matches); - - foreach ($matches[0] as $index => $cell) - { - $cell = trim($cell); - - $Element = array( - 'name' => 'td', - 'handler' => 'line', - 'text' => $cell, - ); - - if (isset($Block['alignments'][$index])) - { - $Element['attributes'] = array( - 'style' => 'text-align: '.$Block['alignments'][$index].';', - ); - } - - $Elements []= $Element; - } - - $Element = array( - 'name' => 'tr', - 'handler' => 'elements', - 'text' => $Elements, - ); - - $Block['element']['text'][1]['text'] []= $Element; - - return $Block; - } - } - - # - # ~ - # - - protected function paragraph($Line) - { - $Block = array( - 'element' => array( - 'name' => 'p', - 'text' => $Line['text'], - 'handler' => 'line', - ), - ); - - return $Block; - } - - # - # Inline Elements - # - - protected $InlineTypes = array( - '"' => array('SpecialCharacter'), - '!' => array('Image'), - '&' => array('SpecialCharacter'), - '*' => array('Emphasis'), - ':' => array('Url'), - '<' => array('UrlTag', 'EmailTag', 'Markup', 'SpecialCharacter'), - '>' => array('SpecialCharacter'), - '[' => array('Link'), - '_' => array('Emphasis'), - '`' => array('Code'), - '~' => array('Strikethrough'), - '\\' => array('EscapeSequence'), - ); - - # ~ - - protected $inlineMarkerList = '!"*_&[:<>`~\\'; - - # - # ~ - # - - public function line($text) - { - $markup = ''; - - $unexaminedText = $text; - - $markerPosition = 0; - - while ($excerpt = strpbrk($unexaminedText, $this->inlineMarkerList)) - { - $marker = $excerpt[0]; - - $markerPosition += strpos($unexaminedText, $marker); - - $Excerpt = array('text' => $excerpt, 'context' => $text); - - foreach ($this->InlineTypes[$marker] as $inlineType) - { - $Inline = $this->{'inline'.$inlineType}($Excerpt); - - if ( ! isset($Inline)) - { - continue; - } - - if (isset($Inline['position']) and $Inline['position'] > $markerPosition) # position is ahead of marker - { - continue; - } - - if ( ! isset($Inline['position'])) - { - $Inline['position'] = $markerPosition; - } - - $unmarkedText = substr($text, 0, $Inline['position']); - - $markup .= $this->unmarkedText($unmarkedText); - - $markup .= isset($Inline['markup']) ? $Inline['markup'] : $this->element($Inline['element']); - - $text = substr($text, $Inline['position'] + $Inline['extent']); - - $unexaminedText = $text; - - $markerPosition = 0; - - continue 2; - } - - $unexaminedText = substr($excerpt, 1); - - $markerPosition ++; - } - - $markup .= $this->unmarkedText($text); - - return $markup; - } - - # - # ~ - # - - protected function inlineCode($Excerpt) - { - $marker = $Excerpt['text'][0]; - - if (preg_match('/^('.$marker.'+)[ ]*(.+?)[ ]*(? strlen($matches[0]), - 'element' => array( - 'name' => 'code', - 'text' => $text, - ), - ); - } - } - - protected function inlineEmailTag($Excerpt) - { - if (strpos($Excerpt['text'], '>') !== false and preg_match('/^<((mailto:)?\S+?@\S+?)>/i', $Excerpt['text'], $matches)) - { - $url = $matches[1]; - - if ( ! isset($matches[2])) - { - $url = 'mailto:' . $url; - } - - return array( - 'extent' => strlen($matches[0]), - 'element' => array( - 'name' => 'a', - 'text' => $matches[1], - 'attributes' => array( - 'href' => $url, - ), - ), - ); - } - } - - protected function inlineEmphasis($Excerpt) - { - if ( ! isset($Excerpt['text'][1])) - { - return; - } - - $marker = $Excerpt['text'][0]; - - if ($Excerpt['text'][1] === $marker and preg_match($this->StrongRegex[$marker], $Excerpt['text'], $matches)) - { - $emphasis = 'strong'; - } - elseif (preg_match($this->EmRegex[$marker], $Excerpt['text'], $matches)) - { - $emphasis = 'em'; - } - else - { - return; - } - - return array( - 'extent' => strlen($matches[0]), - 'element' => array( - 'name' => $emphasis, - 'handler' => 'line', - 'text' => $matches[1], - ), - ); - } - - protected function inlineEscapeSequence($Excerpt) - { - if (isset($Excerpt['text'][1]) and in_array($Excerpt['text'][1], $this->specialCharacters)) - { - return array( - 'markup' => $Excerpt['text'][1], - 'extent' => 2, - ); - } - } - - protected function inlineImage($Excerpt) - { - if ( ! isset($Excerpt['text'][1]) or $Excerpt['text'][1] !== '[') - { - return; - } - - $Excerpt['text']= substr($Excerpt['text'], 1); - - $Link = $this->inlineLink($Excerpt); - - if ($Link === null) - { - return; - } - - $Inline = array( - 'extent' => $Link['extent'] + 1, - 'element' => array( - 'name' => 'img', - 'attributes' => array( - 'src' => $Link['element']['attributes']['href'], - 'alt' => $Link['element']['text'], - ), - ), - ); - - $Inline['element']['attributes'] += $Link['element']['attributes']; - - unset($Inline['element']['attributes']['href']); - - return $Inline; - } - - protected function inlineLink($Excerpt) - { - $Element = array( - 'name' => 'a', - 'handler' => 'line', - 'text' => null, - 'attributes' => array( - 'href' => null, - 'title' => null, - ), - ); - - $extent = 0; - - $remainder = $Excerpt['text']; - - if (preg_match('/\[((?:[^][]|(?R))*)\]/', $remainder, $matches)) - { - $Element['text'] = $matches[1]; - - $extent += strlen($matches[0]); - - $remainder = substr($remainder, $extent); - } - else - { - return; - } - - if (preg_match('/^[(]((?:[^ (]|[(][^ )]+[)])+)(?:[ ]+("[^"]+"|\'[^\']+\'))?[)]/', $remainder, $matches)) - { - $Element['attributes']['href'] = $matches[1]; - - if (isset($matches[2])) - { - $Element['attributes']['title'] = substr($matches[2], 1, - 1); - } - - $extent += strlen($matches[0]); - } - else - { - if (preg_match('/^\s*\[(.*?)\]/', $remainder, $matches)) - { - $definition = $matches[1] ? $matches[1] : $Element['text']; - $definition = strtolower($definition); - - $extent += strlen($matches[0]); - } - else - { - $definition = strtolower($Element['text']); - } - - if ( ! isset($this->DefinitionData['Reference'][$definition])) - { - return; - } - - $Definition = $this->DefinitionData['Reference'][$definition]; - - $Element['attributes']['href'] = $Definition['url']; - $Element['attributes']['title'] = $Definition['title']; - } - - $Element['attributes']['href'] = str_replace(array('&', '<'), array('&', '<'), $Element['attributes']['href']); - - return array( - 'extent' => $extent, - 'element' => $Element, - ); - } - - protected function inlineMarkup($Excerpt) - { - if ($this->markupEscaped or strpos($Excerpt['text'], '>') === false) - { - return; - } - - if ($Excerpt['text'][1] === '/' and preg_match('/^<\/\w*[ ]*>/s', $Excerpt['text'], $matches)) - { - return array( - 'markup' => $matches[0], - 'extent' => strlen($matches[0]), - ); - } - - if ($Excerpt['text'][1] === '!' and preg_match('/^/s', $Excerpt['text'], $matches)) - { - return array( - 'markup' => $matches[0], - 'extent' => strlen($matches[0]), - ); - } - - if ($Excerpt['text'][1] !== ' ' and preg_match('/^<\w*(?:[ ]*'.$this->regexHtmlAttribute.')*[ ]*\/?>/s', $Excerpt['text'], $matches)) - { - return array( - 'markup' => $matches[0], - 'extent' => strlen($matches[0]), - ); - } - } - - protected function inlineSpecialCharacter($Excerpt) - { - if ($Excerpt['text'][0] === '&' and ! preg_match('/^&#?\w+;/', $Excerpt['text'])) - { - return array( - 'markup' => '&', - 'extent' => 1, - ); - } - - $SpecialCharacter = array('>' => 'gt', '<' => 'lt', '"' => 'quot'); - - if (isset($SpecialCharacter[$Excerpt['text'][0]])) - { - return array( - 'markup' => '&'.$SpecialCharacter[$Excerpt['text'][0]].';', - 'extent' => 1, - ); - } - } - - protected function inlineStrikethrough($Excerpt) - { - if ( ! isset($Excerpt['text'][1])) - { - return; - } - - if ($Excerpt['text'][1] === '~' and preg_match('/^~~(?=\S)(.+?)(?<=\S)~~/', $Excerpt['text'], $matches)) - { - return array( - 'extent' => strlen($matches[0]), - 'element' => array( - 'name' => 'del', - 'text' => $matches[1], - 'handler' => 'line', - ), - ); - } - } - - protected function inlineUrl($Excerpt) - { - if ($this->urlsLinked !== true or ! isset($Excerpt['text'][2]) or $Excerpt['text'][2] !== '/') - { - return; - } - - if (preg_match('/\bhttps?:[\/]{2}[^\s<]+\b\/*/ui', $Excerpt['context'], $matches, PREG_OFFSET_CAPTURE)) - { - $Inline = array( - 'extent' => strlen($matches[0][0]), - 'position' => $matches[0][1], - 'element' => array( - 'name' => 'a', - 'text' => $matches[0][0], - 'attributes' => array( - 'href' => $matches[0][0], - ), - ), - ); - - return $Inline; - } - } - - protected function inlineUrlTag($Excerpt) - { - if (strpos($Excerpt['text'], '>') !== false and preg_match('/^<(\w+:\/{2}[^ >]+)>/i', $Excerpt['text'], $matches)) - { - $url = str_replace(array('&', '<'), array('&', '<'), $matches[1]); - - return array( - 'extent' => strlen($matches[0]), - 'element' => array( - 'name' => 'a', - 'text' => $url, - 'attributes' => array( - 'href' => $url, - ), - ), - ); - } - } - - # - # ~ - - protected $unmarkedInlineTypes = array("\n" => 'Break', '://' => 'Url'); - - # ~ - - protected function unmarkedText($text) - { - if ($this->breaksEnabled) - { - $text = preg_replace('/[ ]*\n/', "
\n", $text); - } - else - { - $text = preg_replace('/(?:[ ][ ]+|[ ]*\\\\)\n/', "
\n", $text); - $text = str_replace(" \n", "\n", $text); - } - - return $text; - } - - # - # Handlers - # - - protected function element(array $Element) - { - $markup = '<'.$Element['name']; - - if (isset($Element['attributes'])) - { - foreach ($Element['attributes'] as $name => $value) - { - if ($value === null) - { - continue; - } - - $markup .= ' '.$name.'="'.$value.'"'; - } - } - - if (isset($Element['text'])) - { - $markup .= '>'; - - if (isset($Element['handler'])) - { - $markup .= $this->{$Element['handler']}($Element['text']); - } - else - { - $markup .= $Element['text']; - } - - $markup .= ''; - } - else - { - $markup .= ' />'; - } - - return $markup; - } - - protected function elements(array $Elements) - { - $markup = ''; - - foreach ($Elements as $Element) - { - $markup .= "\n" . $this->element($Element); - } - - $markup .= "\n"; - - return $markup; - } - - # ~ - - protected function li($lines) - { - $markup = $this->lines($lines); - - $trimmedMarkup = trim($markup); - - if ( ! in_array('', $lines) and substr($trimmedMarkup, 0, 3) === '

') - { - $markup = $trimmedMarkup; - $markup = substr($markup, 3); - - $position = strpos($markup, "

"); - - $markup = substr_replace($markup, '', $position, 4); - } - - return $markup; - } - - # - # Deprecated Methods - # - - function parse($text) - { - $markup = $this->text($text); - - return $markup; - } - - # - # Static Methods - # - - static function instance($name = 'default') - { - if (isset(self::$instances[$name])) - { - return self::$instances[$name]; - } - - $instance = new self(); - - self::$instances[$name] = $instance; - - return $instance; - } - - private static $instances = array(); - - # - # Fields - # - - protected $DefinitionData; - - # - # Read-Only - - protected $specialCharacters = array( - '\\', '`', '*', '_', '{', '}', '[', ']', '(', ')', '>', '#', '+', '-', '.', '!', '|', - ); - - protected $StrongRegex = array( - '*' => '/^[*]{2}((?:\\\\\*|[^*]|[*][^*]*[*])+?)[*]{2}(?![*])/s', - '_' => '/^__((?:\\\\_|[^_]|_[^_]*_)+?)__(?!_)/us', - ); - - protected $EmRegex = array( - '*' => '/^[*]((?:\\\\\*|[^*]|[*][*][^*]+?[*][*])+?)[*](?![*])/s', - '_' => '/^_((?:\\\\_|[^_]|__[^_]*__)+?)_(?!_)\b/us', - ); - - protected $regexHtmlAttribute = '[a-zA-Z_:][\w:.-]*(?:\s*=\s*(?:[^"\'=<>`\s]+|"[^"]*"|\'[^\']*\'))?'; - - protected $voidElements = array( - 'area', 'base', 'br', 'col', 'command', 'embed', 'hr', 'img', 'input', 'link', 'meta', 'param', 'source', - ); - - protected $textLevelElements = array( - 'a', 'br', 'bdo', 'abbr', 'blink', 'nextid', 'acronym', 'basefont', - 'b', 'em', 'big', 'cite', 'small', 'spacer', 'listing', - 'i', 'rp', 'del', 'code', 'strike', 'marquee', - 'q', 'rt', 'ins', 'font', 'strong', - 's', 'tt', 'sub', 'mark', - 'u', 'xm', 'sup', 'nobr', - 'var', 'ruby', - 'wbr', 'span', - 'time', - ); -} diff --git a/vendor/yahnis-elsts/plugin-update-checker/vendor/PucReadmeParser.php b/vendor/yahnis-elsts/plugin-update-checker/vendor/PucReadmeParser.php index 1f5cec9e1..a794c49ac 100644 --- a/vendor/yahnis-elsts/plugin-update-checker/vendor/PucReadmeParser.php +++ b/vendor/yahnis-elsts/plugin-update-checker/vendor/PucReadmeParser.php @@ -241,7 +241,11 @@ function user_sanitize( $text, $strict = false ) { // whitelisted chars } function sanitize_text( $text ) { // not fancy - $text = strip_tags($text); + $text = function_exists('wp_strip_all_tags') + ? wp_strip_all_tags($text) + //phpcs:ignore WordPressVIPMinimum.Functions.StripTags.StripTagsOneParameter -- Using wp_strip_all_tags() if available + : strip_tags($text); + $text = esc_html($text); $text = trim($text); return $text;