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 fcbad1b6f..5cd2d40ce 100644 --- a/.gitattributes +++ b/.gitattributes @@ -2,3 +2,11 @@ /.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/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/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/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;