From aa429e6fa625dc45861768197aa221e03522f43b Mon Sep 17 00:00:00 2001 From: Anh Tran Date: Thu, 9 Jan 2025 14:14:17 +0700 Subject: [PATCH] Use Meta Box Updater --- .github/workflows/release.yml | 33 +- composer.json | 13 +- composer.lock | 60 +- meta-box-lite.php | 15 - modules/meta-box/css/image-select.css | 20 +- modules/meta-box/css/key-value.css | 1 - modules/meta-box/inc/field.php | 17 +- modules/meta-box/inc/fields/fieldset-text.php | 4 + modules/meta-box/inc/fields/image-select.php | 1 + modules/meta-box/inc/fields/key-value.php | 17 +- modules/meta-box/js/date.js | 25 +- modules/meta-box/js/datetime.js | 29 +- modules/meta-box/js/image-select.js | 27 + modules/meta-box/js/time.js | 7 +- modules/meta-box/src/Updater/Checker.php | 182 ++ modules/meta-box/src/Updater/Notification.php | 116 ++ modules/meta-box/src/Updater/Option.php | 59 + modules/meta-box/src/Updater/Settings.php | 147 ++ vendor/composer/autoload_files.php | 1 - vendor/composer/autoload_static.php | 1 - vendor/composer/installed.json | 62 +- vendor/composer/installed.php | 31 +- vendor/composer/platform_check.php | 4 +- .../Puc/v5/PucFactory.php | 10 - .../Puc/v5p5/Autoloader.php | 86 - .../Puc/v5p5/DebugBar/Extension.php | 199 --- .../Puc/v5p5/DebugBar/Panel.php | 186 -- .../Puc/v5p5/DebugBar/PluginExtension.php | 40 - .../Puc/v5p5/DebugBar/PluginPanel.php | 47 - .../Puc/v5p5/DebugBar/ThemePanel.php | 25 - .../Puc/v5p5/InstalledPackage.php | 105 -- .../Puc/v5p5/Metadata.php | 162 -- .../Puc/v5p5/OAuthSignature.php | 102 -- .../Puc/v5p5/Plugin/Package.php | 188 -- .../Puc/v5p5/Plugin/PluginInfo.php | 136 -- .../Puc/v5p5/Plugin/Ui.php | 294 ---- .../Puc/v5p5/Plugin/Update.php | 116 -- .../Puc/v5p5/Plugin/UpdateChecker.php | 425 ----- .../Puc/v5p5/PucFactory.php | 362 ---- .../Puc/v5p5/Scheduler.php | 300 ---- .../Puc/v5p5/StateStore.php | 214 --- .../Puc/v5p5/Theme/Package.php | 69 - .../Puc/v5p5/Theme/Update.php | 88 - .../Puc/v5p5/Theme/UpdateChecker.php | 159 -- .../plugin-update-checker/Puc/v5p5/Update.php | 38 - .../Puc/v5p5/UpdateChecker.php | 1141 ------------ .../Puc/v5p5/UpgraderStatus.php | 200 --- .../plugin-update-checker/Puc/v5p5/Utils.php | 70 - .../Puc/v5p5/Vcs/Api.php | 379 ---- .../Puc/v5p5/Vcs/BaseChecker.php | 29 - .../Puc/v5p5/Vcs/BitBucketApi.php | 272 --- .../Puc/v5p5/Vcs/GitHubApi.php | 467 ----- .../Puc/v5p5/Vcs/GitLabApi.php | 414 ----- .../Puc/v5p5/Vcs/PluginUpdateChecker.php | 275 --- .../Puc/v5p5/Vcs/Reference.php | 51 - .../Puc/v5p5/Vcs/ReleaseAssetSupport.php | 83 - .../Puc/v5p5/Vcs/ReleaseFilteringFeature.php | 108 -- .../Puc/v5p5/Vcs/ThemeUpdateChecker.php | 83 - .../Puc/v5p5/Vcs/VcsCheckerMethods.php | 59 - .../Puc/v5p5/WpCliCheckTrigger.php | 84 - .../css/puc-debug-bar.css | 70 - .../plugin-update-checker/js/debug-bar.js | 54 - .../languages/plugin-update-checker-ca.mo | Bin 1186 -> 0 bytes .../languages/plugin-update-checker-cs_CZ.mo | Bin 1077 -> 0 bytes .../languages/plugin-update-checker-da_DK.mo | Bin 1010 -> 0 bytes .../languages/plugin-update-checker-de_DE.mo | Bin 980 -> 0 bytes .../languages/plugin-update-checker-el.mo | Bin 1455 -> 0 bytes .../languages/plugin-update-checker-es_AR.mo | Bin 1140 -> 0 bytes .../languages/plugin-update-checker-es_CL.mo | Bin 1140 -> 0 bytes .../languages/plugin-update-checker-es_CO.mo | Bin 1140 -> 0 bytes .../languages/plugin-update-checker-es_CR.mo | Bin 1140 -> 0 bytes .../languages/plugin-update-checker-es_DO.mo | Bin 1140 -> 0 bytes .../languages/plugin-update-checker-es_ES.mo | Bin 1140 -> 0 bytes .../languages/plugin-update-checker-es_GT.mo | Bin 1140 -> 0 bytes .../languages/plugin-update-checker-es_HN.mo | Bin 1140 -> 0 bytes .../languages/plugin-update-checker-es_MX.mo | Bin 1140 -> 0 bytes .../languages/plugin-update-checker-es_PE.mo | Bin 1140 -> 0 bytes .../languages/plugin-update-checker-es_PR.mo | Bin 1140 -> 0 bytes .../languages/plugin-update-checker-es_UY.mo | Bin 1140 -> 0 bytes .../languages/plugin-update-checker-es_VE.mo | Bin 1140 -> 0 bytes .../languages/plugin-update-checker-fa_IR.mo | Bin 1128 -> 0 bytes .../languages/plugin-update-checker-fr_CA.mo | Bin 1208 -> 0 bytes .../languages/plugin-update-checker-fr_FR.mo | Bin 1066 -> 0 bytes .../languages/plugin-update-checker-hu_HU.mo | Bin 982 -> 0 bytes .../languages/plugin-update-checker-it_IT.mo | Bin 1135 -> 0 bytes .../languages/plugin-update-checker-ja.mo | Bin 1454 -> 0 bytes .../languages/plugin-update-checker-nl_BE.mo | Bin 1211 -> 0 bytes .../languages/plugin-update-checker-nl_NL.mo | Bin 1211 -> 0 bytes .../languages/plugin-update-checker-pt_BR.mo | Bin 1014 -> 0 bytes .../languages/plugin-update-checker-ru_RU.mo | Bin 1337 -> 0 bytes .../languages/plugin-update-checker-sl_SI.mo | Bin 1203 -> 0 bytes .../languages/plugin-update-checker-sv_SE.mo | Bin 1006 -> 0 bytes .../languages/plugin-update-checker-tr_TR.mo | Bin 1118 -> 0 bytes .../languages/plugin-update-checker-uk_UA.mo | Bin 1309 -> 0 bytes .../languages/plugin-update-checker-zh_CN.mo | Bin 1174 -> 0 bytes .../languages/plugin-update-checker.pot | 49 - .../plugin-update-checker/load-v5p5.php | 34 - .../plugin-update-checker.php | 10 - .../vendor/Parsedown.php | 4 - .../vendor/ParsedownModern.php | 1538 ----------------- .../vendor/PucReadmeParser.php | 352 ---- 101 files changed, 626 insertions(+), 9423 deletions(-) create mode 100644 modules/meta-box/js/image-select.js create mode 100644 modules/meta-box/src/Updater/Checker.php create mode 100644 modules/meta-box/src/Updater/Notification.php create mode 100644 modules/meta-box/src/Updater/Option.php create mode 100644 modules/meta-box/src/Updater/Settings.php delete mode 100644 vendor/yahnis-elsts/plugin-update-checker/Puc/v5/PucFactory.php delete mode 100644 vendor/yahnis-elsts/plugin-update-checker/Puc/v5p5/Autoloader.php delete mode 100644 vendor/yahnis-elsts/plugin-update-checker/Puc/v5p5/DebugBar/Extension.php delete mode 100644 vendor/yahnis-elsts/plugin-update-checker/Puc/v5p5/DebugBar/Panel.php delete mode 100644 vendor/yahnis-elsts/plugin-update-checker/Puc/v5p5/DebugBar/PluginExtension.php delete mode 100644 vendor/yahnis-elsts/plugin-update-checker/Puc/v5p5/DebugBar/PluginPanel.php delete mode 100644 vendor/yahnis-elsts/plugin-update-checker/Puc/v5p5/DebugBar/ThemePanel.php delete mode 100644 vendor/yahnis-elsts/plugin-update-checker/Puc/v5p5/InstalledPackage.php delete mode 100644 vendor/yahnis-elsts/plugin-update-checker/Puc/v5p5/Metadata.php delete mode 100644 vendor/yahnis-elsts/plugin-update-checker/Puc/v5p5/OAuthSignature.php delete mode 100644 vendor/yahnis-elsts/plugin-update-checker/Puc/v5p5/Plugin/Package.php delete mode 100644 vendor/yahnis-elsts/plugin-update-checker/Puc/v5p5/Plugin/PluginInfo.php delete mode 100644 vendor/yahnis-elsts/plugin-update-checker/Puc/v5p5/Plugin/Ui.php delete mode 100644 vendor/yahnis-elsts/plugin-update-checker/Puc/v5p5/Plugin/Update.php delete mode 100644 vendor/yahnis-elsts/plugin-update-checker/Puc/v5p5/Plugin/UpdateChecker.php delete mode 100644 vendor/yahnis-elsts/plugin-update-checker/Puc/v5p5/PucFactory.php delete mode 100644 vendor/yahnis-elsts/plugin-update-checker/Puc/v5p5/Scheduler.php delete mode 100644 vendor/yahnis-elsts/plugin-update-checker/Puc/v5p5/StateStore.php delete mode 100644 vendor/yahnis-elsts/plugin-update-checker/Puc/v5p5/Theme/Package.php delete mode 100644 vendor/yahnis-elsts/plugin-update-checker/Puc/v5p5/Theme/Update.php delete mode 100644 vendor/yahnis-elsts/plugin-update-checker/Puc/v5p5/Theme/UpdateChecker.php delete mode 100644 vendor/yahnis-elsts/plugin-update-checker/Puc/v5p5/Update.php delete mode 100644 vendor/yahnis-elsts/plugin-update-checker/Puc/v5p5/UpdateChecker.php delete mode 100644 vendor/yahnis-elsts/plugin-update-checker/Puc/v5p5/UpgraderStatus.php delete mode 100644 vendor/yahnis-elsts/plugin-update-checker/Puc/v5p5/Utils.php delete mode 100644 vendor/yahnis-elsts/plugin-update-checker/Puc/v5p5/Vcs/Api.php delete mode 100644 vendor/yahnis-elsts/plugin-update-checker/Puc/v5p5/Vcs/BaseChecker.php delete mode 100644 vendor/yahnis-elsts/plugin-update-checker/Puc/v5p5/Vcs/BitBucketApi.php delete mode 100644 vendor/yahnis-elsts/plugin-update-checker/Puc/v5p5/Vcs/GitHubApi.php delete mode 100644 vendor/yahnis-elsts/plugin-update-checker/Puc/v5p5/Vcs/GitLabApi.php delete mode 100644 vendor/yahnis-elsts/plugin-update-checker/Puc/v5p5/Vcs/PluginUpdateChecker.php delete mode 100644 vendor/yahnis-elsts/plugin-update-checker/Puc/v5p5/Vcs/Reference.php delete mode 100644 vendor/yahnis-elsts/plugin-update-checker/Puc/v5p5/Vcs/ReleaseAssetSupport.php delete mode 100644 vendor/yahnis-elsts/plugin-update-checker/Puc/v5p5/Vcs/ReleaseFilteringFeature.php delete mode 100644 vendor/yahnis-elsts/plugin-update-checker/Puc/v5p5/Vcs/ThemeUpdateChecker.php delete mode 100644 vendor/yahnis-elsts/plugin-update-checker/Puc/v5p5/Vcs/VcsCheckerMethods.php delete mode 100644 vendor/yahnis-elsts/plugin-update-checker/Puc/v5p5/WpCliCheckTrigger.php delete mode 100644 vendor/yahnis-elsts/plugin-update-checker/css/puc-debug-bar.css delete mode 100644 vendor/yahnis-elsts/plugin-update-checker/js/debug-bar.js delete mode 100644 vendor/yahnis-elsts/plugin-update-checker/languages/plugin-update-checker-ca.mo delete mode 100644 vendor/yahnis-elsts/plugin-update-checker/languages/plugin-update-checker-cs_CZ.mo delete mode 100644 vendor/yahnis-elsts/plugin-update-checker/languages/plugin-update-checker-da_DK.mo delete mode 100644 vendor/yahnis-elsts/plugin-update-checker/languages/plugin-update-checker-de_DE.mo delete mode 100644 vendor/yahnis-elsts/plugin-update-checker/languages/plugin-update-checker-el.mo delete mode 100644 vendor/yahnis-elsts/plugin-update-checker/languages/plugin-update-checker-es_AR.mo delete mode 100644 vendor/yahnis-elsts/plugin-update-checker/languages/plugin-update-checker-es_CL.mo delete mode 100644 vendor/yahnis-elsts/plugin-update-checker/languages/plugin-update-checker-es_CO.mo delete mode 100644 vendor/yahnis-elsts/plugin-update-checker/languages/plugin-update-checker-es_CR.mo delete mode 100644 vendor/yahnis-elsts/plugin-update-checker/languages/plugin-update-checker-es_DO.mo delete mode 100644 vendor/yahnis-elsts/plugin-update-checker/languages/plugin-update-checker-es_ES.mo delete mode 100644 vendor/yahnis-elsts/plugin-update-checker/languages/plugin-update-checker-es_GT.mo delete mode 100644 vendor/yahnis-elsts/plugin-update-checker/languages/plugin-update-checker-es_HN.mo delete mode 100644 vendor/yahnis-elsts/plugin-update-checker/languages/plugin-update-checker-es_MX.mo delete mode 100644 vendor/yahnis-elsts/plugin-update-checker/languages/plugin-update-checker-es_PE.mo delete mode 100644 vendor/yahnis-elsts/plugin-update-checker/languages/plugin-update-checker-es_PR.mo delete mode 100644 vendor/yahnis-elsts/plugin-update-checker/languages/plugin-update-checker-es_UY.mo delete mode 100644 vendor/yahnis-elsts/plugin-update-checker/languages/plugin-update-checker-es_VE.mo delete mode 100644 vendor/yahnis-elsts/plugin-update-checker/languages/plugin-update-checker-fa_IR.mo delete mode 100644 vendor/yahnis-elsts/plugin-update-checker/languages/plugin-update-checker-fr_CA.mo delete mode 100644 vendor/yahnis-elsts/plugin-update-checker/languages/plugin-update-checker-fr_FR.mo delete mode 100644 vendor/yahnis-elsts/plugin-update-checker/languages/plugin-update-checker-hu_HU.mo delete mode 100644 vendor/yahnis-elsts/plugin-update-checker/languages/plugin-update-checker-it_IT.mo delete mode 100644 vendor/yahnis-elsts/plugin-update-checker/languages/plugin-update-checker-ja.mo delete mode 100644 vendor/yahnis-elsts/plugin-update-checker/languages/plugin-update-checker-nl_BE.mo delete mode 100644 vendor/yahnis-elsts/plugin-update-checker/languages/plugin-update-checker-nl_NL.mo delete mode 100644 vendor/yahnis-elsts/plugin-update-checker/languages/plugin-update-checker-pt_BR.mo delete mode 100644 vendor/yahnis-elsts/plugin-update-checker/languages/plugin-update-checker-ru_RU.mo delete mode 100644 vendor/yahnis-elsts/plugin-update-checker/languages/plugin-update-checker-sl_SI.mo delete mode 100644 vendor/yahnis-elsts/plugin-update-checker/languages/plugin-update-checker-sv_SE.mo delete mode 100644 vendor/yahnis-elsts/plugin-update-checker/languages/plugin-update-checker-tr_TR.mo delete mode 100644 vendor/yahnis-elsts/plugin-update-checker/languages/plugin-update-checker-uk_UA.mo delete mode 100644 vendor/yahnis-elsts/plugin-update-checker/languages/plugin-update-checker-zh_CN.mo delete mode 100644 vendor/yahnis-elsts/plugin-update-checker/languages/plugin-update-checker.pot delete mode 100644 vendor/yahnis-elsts/plugin-update-checker/load-v5p5.php delete mode 100644 vendor/yahnis-elsts/plugin-update-checker/plugin-update-checker.php delete mode 100644 vendor/yahnis-elsts/plugin-update-checker/vendor/Parsedown.php delete mode 100644 vendor/yahnis-elsts/plugin-update-checker/vendor/ParsedownModern.php delete mode 100644 vendor/yahnis-elsts/plugin-update-checker/vendor/PucReadmeParser.php diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 822d5fd..e48d4ed 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -1,31 +1,18 @@ name: Release on: workflow_dispatch: - branch: + branches: - main push: tags: - "*" jobs: - release: - name: Release - runs-on: ubuntu-latest - steps: - - name: Checkout - uses: actions/checkout@v2 - - name: Create zip - run: | - name=${{ github.event.repository.name }} - git archive -o $name.zip --prefix=$name/ HEAD - - name: Release - uses: softprops/action-gh-release@v2 - if: startsWith(github.ref, 'refs/tags/') - with: - files: ${{ github.event.repository.name }}.zip - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - - name: Notify Slack - run: | - tag=$(git describe --tags `git rev-list --tags --max-count=1`) - name=${{ github.event.repository.name }} - curl -X POST --data-urlencode "payload={\"channel\": \"#meta-box\", \"username\": \"Bot\", \"text\": \"New version $tag for $name has been just released!\", \"icon_emoji\": \":tada:\"}" ${{ secrets.SLACK_WEBHOOK }} \ No newline at end of file + call-workflow: + uses: wpmetabox/meta-box/.github/workflows/extension.yml@master + secrets: + SSH_KEY: ${{ secrets.SSH_KEY }} + SSH_KNOWN_HOSTS: ${{ secrets.SSH_KNOWN_HOSTS }} + SSH_USERNAME: ${{ secrets.SSH_USERNAME }} + SERVER_IP: ${{ secrets.SERVER_IP }} + DOWNLOADS_DIR: ${{ secrets.DOWNLOADS_DIR }} + SLACK_WEBHOOK: ${{ secrets.SLACK_WEBHOOK }} diff --git a/composer.json b/composer.json index dce6449..0519082 100644 --- a/composer.json +++ b/composer.json @@ -74,11 +74,10 @@ "wpmetabox/mb-relationships": "dev-master", "wpmetabox/mb-rest-api": "dev-master", "wpmetabox/mb-yoast-seo": "dev-master", - "wpmetabox/meta-box": "dev-master", + "wpmetabox/meta-box": "^5.10", "wpmetabox/meta-box-beaver-themer-integrator": "dev-master", "wpmetabox/meta-box-facetwp-integrator": "dev-master", - "wpmetabox/text-limiter": "dev-master", - "yahnis-elsts/plugin-update-checker": "^5.5" + "wpmetabox/text-limiter": "dev-master" }, "minimum-stability": "dev", "prefer-stable": true, @@ -88,18 +87,14 @@ "rm -rf vendor/**/**/.git", "rm -rf modules/**/.git", "echo Cleaning up plugin headers...", - "php cleanup.php", - "echo Removing Meta Box updater...", - "rm -rf modules/meta-box/src/Updater/" + "php cleanup.php" ], "post-install-cmd": [ "echo Deleting .git dirs...", "rm -rf vendor/**/**/.git", "rm -rf modules/**/.git", "echo Cleaning up plugin headers...", - "php cleanup.php", - "echo Removing Meta Box updater...", - "rm -rf modules/meta-box/src/Updater/" + "php cleanup.php" ] }, "extra": { diff --git a/composer.lock b/composer.lock index a8ec6bc..37a92fc 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "b2442f6acd0fad51a96c5134ed56f066", + "content-hash": "50712d73fbed87cd52ee2d447a66b018", "packages": [ { "name": "composer/installers", @@ -777,11 +777,11 @@ }, { "name": "wpmetabox/meta-box", - "version": "dev-master", + "version": "5.10.5", "source": { "type": "git", "url": "git@github.com:wpmetabox/meta-box.git", - "reference": "872dbd07d6ec90b3c5b5530e19e5f724c49797e3" + "reference": "3fa649ba0e8624c71f066a8437a4a47af5998710" }, "require": { "meta-box/support": "dev-master" @@ -789,7 +789,6 @@ "require-dev": { "phpunit/phpunit": "^11.3" }, - "default-branch": true, "type": "wordpress-plugin", "extra": { "dev-files": { @@ -867,7 +866,7 @@ "wordpress", "wordpress-plugin" ], - "time": "2024-12-23T02:09:08+00:00" + "time": "2024-12-16T06:50:30+00:00" }, { "name": "wpmetabox/meta-box-beaver-themer-integrator", @@ -1000,56 +999,6 @@ "source": "https://github.com/wpmetabox/meta-box-text-limiter/tree/master" }, "time": "2024-12-23T02:38:41+00:00" - }, - { - "name": "yahnis-elsts/plugin-update-checker", - "version": "v5.5", - "source": { - "type": "git", - "url": "https://github.com/YahnisElsts/plugin-update-checker.git", - "reference": "845d65da93bcff31649ede00d9d73b1beadbb7f0" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/YahnisElsts/plugin-update-checker/zipball/845d65da93bcff31649ede00d9d73b1beadbb7f0", - "reference": "845d65da93bcff31649ede00d9d73b1beadbb7f0", - "shasum": "" - }, - "require": { - "ext-json": "*", - "php": ">=5.6.20" - }, - "type": "library", - "autoload": { - "files": [ - "load-v5p5.php" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Yahnis Elsts", - "email": "whiteshadow@w-shadow.com", - "homepage": "https://w-shadow.com/", - "role": "Developer" - } - ], - "description": "A custom update checker for WordPress plugins and themes. Useful if you can't host your plugin in the official WP repository but still want it to support automatic updates.", - "homepage": "https://github.com/YahnisElsts/plugin-update-checker/", - "keywords": [ - "automatic updates", - "plugin updates", - "theme updates", - "wordpress" - ], - "support": { - "issues": "https://github.com/YahnisElsts/plugin-update-checker/issues", - "source": "https://github.com/YahnisElsts/plugin-update-checker/tree/v5.5" - }, - "time": "2024-10-16T14:25:00+00:00" } ], "packages-dev": [], @@ -1068,7 +1017,6 @@ "wpmetabox/mb-relationships": 20, "wpmetabox/mb-rest-api": 20, "wpmetabox/mb-yoast-seo": 20, - "wpmetabox/meta-box": 20, "wpmetabox/meta-box-beaver-themer-integrator": 20, "wpmetabox/meta-box-facetwp-integrator": 20, "wpmetabox/text-limiter": 20 diff --git a/meta-box-lite.php b/meta-box-lite.php index 37adb1f..9c14828 100644 --- a/meta-box-lite.php +++ b/meta-box-lite.php @@ -10,23 +10,8 @@ * Text Domain: meta-box-lite */ -use YahnisElsts\PluginUpdateChecker\v5\PucFactory; - if ( ! defined( 'ABSPATH' ) ) { return; } require_once __DIR__ . '/vendor/autoload.php'; - -$mbl_update_checker = PucFactory::buildUpdateChecker( - 'https://github.com/wpmetabox/meta-box-lite/', - __FILE__, - 'meta-box-lite' -); -$mbl_update_checker->setBranch( 'main' ); - -$mbl_update_checker->addResultFilter( function ( $info, $response = null ): void { - $info->icons = [ - 'default' => 'https://i0.wp.com/metabox.io/wp-content/uploads/2015/08/logo.png', - ]; -} ); \ No newline at end of file diff --git a/modules/meta-box/css/image-select.css b/modules/meta-box/css/image-select.css index d15344f..1e9ecbe 100644 --- a/modules/meta-box/css/image-select.css +++ b/modules/meta-box/css/image-select.css @@ -1,31 +1,21 @@ .rwmb-image-select { + display: inline-block; width: 80px; height: 80px; float: left; - margin: 0 8px 8px 0; + margin: 0 10px 10px 0; border: 3px solid #d8d8d8; - border-radius: 4px; + border-radius: 3px; padding: 1px; - cursor: pointer; - - --color: #2271b1; } - -.block-editor-page .rwmb-image-select { - --color: var(--wp-admin-theme-color, #2271b1); -} - .rwmb-image-select img { width: 100%; height: 100%; - object-fit: cover; } - .rwmb-image-select:hover, -.rwmb-image-select:has(:checked) { - border-color: var(--color); +.rwmb-image-select.rwmb-active { + border-color: #0074a2; } - .rwmb-image_select.rwmb-image_select { display: none; } diff --git a/modules/meta-box/css/key-value.css b/modules/meta-box/css/key-value.css index 69f0292..748648c 100644 --- a/modules/meta-box/css/key-value.css +++ b/modules/meta-box/css/key-value.css @@ -1,7 +1,6 @@ .rwmb-key_value-clone { display: flex; align-items: center; - gap: 8px; } .rwmb-key_value-clone input { flex: 1; diff --git a/modules/meta-box/inc/field.php b/modules/meta-box/inc/field.php index 393d56d..cc12baf 100644 --- a/modules/meta-box/inc/field.php +++ b/modules/meta-box/inc/field.php @@ -38,7 +38,7 @@ public static function show( array $field, bool $saved, $post_id = 0 ) { } $end = static::end_html( $field ); - $end = self::filter( 'end_html', $end, $field, $meta ); + $end = self::filter( 'end_html', $end, $field, $meta ); $html = self::filter( 'wrapper_html', $begin . $field_html . $end, $field, $meta ); // Display label and input in DIV and allow user-defined classes to be appended. @@ -75,15 +75,20 @@ public static function html( $meta, $field ) { protected static function begin_html( array $field ): string { $id = $field['attributes']['id'] ?? $field['id']; $required = $field['required'] || ! empty( $field['attributes']['required'] ); - $required = $required ? '*' : ''; $label = $field['name'] ? sprintf( - // Translators: %1$s - field ID, %2$s - field label, %3$s - required asterisk, %4$s - label description. - '
%4$s
', + '', esc_attr( $id ), $field['name'], - $required, - static::label_description( $field ) + $required ? '*' : '' + ) : ''; + + $label .= static::label_description( $field ); + + $label = $label ? sprintf( + '
%s
', + esc_attr( $id ), + $label ) : ''; $data_min_clone = is_numeric( $field['min_clone'] ) && $field['min_clone'] > 1 ? ' data-min-clone=' . $field['min_clone'] : ''; diff --git a/modules/meta-box/inc/fields/fieldset-text.php b/modules/meta-box/inc/fields/fieldset-text.php index 1aaa147..907c801 100644 --- a/modules/meta-box/inc/fields/fieldset-text.php +++ b/modules/meta-box/inc/fields/fieldset-text.php @@ -41,6 +41,10 @@ protected static function input_description( array $field ) : string { return ''; } + protected static function label_description( array $field ) : string { + return ''; + } + /** * Normalize parameters for field. * diff --git a/modules/meta-box/inc/fields/image-select.php b/modules/meta-box/inc/fields/image-select.php index 38f9d6b..23c2f4a 100644 --- a/modules/meta-box/inc/fields/image-select.php +++ b/modules/meta-box/inc/fields/image-select.php @@ -8,6 +8,7 @@ class RWMB_Image_Select_Field extends RWMB_Field { public static function admin_enqueue_scripts() { wp_enqueue_style( 'rwmb-image-select', RWMB_CSS_URL . 'image-select.css', [], RWMB_VER ); wp_style_add_data( 'rwmb-image-select', 'path', RWMB_CSS_DIR . 'image-select.css' ); + wp_enqueue_script( 'rwmb-image-select', RWMB_JS_URL . 'image-select.js', [ 'jquery' ], RWMB_VER, true ); } /** diff --git a/modules/meta-box/inc/fields/key-value.php b/modules/meta-box/inc/fields/key-value.php index 542844a..6a1cd61 100644 --- a/modules/meta-box/inc/fields/key-value.php +++ b/modules/meta-box/inc/fields/key-value.php @@ -35,7 +35,22 @@ public static function html( $meta, $field ) { } protected static function begin_html( array $field ) : string { - return parent::begin_html( $field ) . parent::input_description( $field ); + $desc = $field['desc'] ? "

{$field['desc']}

" : ''; + + if ( empty( $field['name'] ) ) { + return '
' . $desc; + } + + return sprintf( + '
+ +
+
+ %s', + $field['id'], + $field['name'], + $desc + ); } protected static function input_description( array $field ) : string { diff --git a/modules/meta-box/js/date.js b/modules/meta-box/js/date.js index ee99109..3a8451f 100644 --- a/modules/meta-box/js/date.js +++ b/modules/meta-box/js/date.js @@ -5,28 +5,23 @@ * Transform an input into a date picker. */ function transform() { - let $this = $( this ), - options = $this.data( 'options' ); - - let $inline = $this.siblings( '.rwmb-datetime-inline' ); - if ( !$inline.length ) { - $inline = $this.closest( '.rwmb-input-group' ).siblings( '.rwmb-datetime-inline' ); - } - - let $timestamp = $this.siblings( '.rwmb-datetime-timestamp' ), + var $this = $( this ), + options = $this.data( 'options' ), + $inline = $this.siblings( '.rwmb-datetime-inline' ), + $timestamp = $this.siblings( '.rwmb-datetime-timestamp' ), current = $this.val(), $picker = $inline.length ? $inline : $this; $this.siblings( '.ui-datepicker-append' ).remove(); // Remove appended text - options.onSelect = function () { + options.onSelect = function() { $this.trigger( 'change' ); - }; - options.beforeShow = function ( i ) { + } + options.beforeShow = function( i ) { if ( $( i ).prop( 'readonly' ) ) { return false; } - }; + } if ( $timestamp.length ) { options.onClose = options.onSelect = function () { @@ -41,7 +36,7 @@ } ); } - if ( !$inline.length ) { + if ( ! $inline.length ) { $this.removeClass( 'hasDatepicker' ).datepicker( options ); return; } @@ -49,7 +44,7 @@ options.altField = '#' + $this.attr( 'id' ); $this.on( 'keydown', _.debounce( function () { // if val is empty, return to allow empty datepicker input. - if ( !$this.val() ) { + if ( ! $this.val() ) { return; } $picker diff --git a/modules/meta-box/js/datetime.js b/modules/meta-box/js/datetime.js index 5cf26f8..e8d1c72 100644 --- a/modules/meta-box/js/datetime.js +++ b/modules/meta-box/js/datetime.js @@ -5,28 +5,23 @@ * Transform an input into a datetime picker. */ function transform() { - let $this = $( this ), - options = $this.data( 'options' ); - - let $inline = $this.siblings( '.rwmb-datetime-inline' ); - if ( !$inline.length ) { - $inline = $this.closest( '.rwmb-input-group' ).siblings( '.rwmb-datetime-inline' ); - } - - let $timestamp = $this.siblings( '.rwmb-datetime-timestamp' ), + var $this = $( this ), + options = $this.data( 'options' ), + $inline = $this.siblings( '.rwmb-datetime-inline' ), + $timestamp = $this.siblings( '.rwmb-datetime-timestamp' ), current = $this.val(), $picker = $inline.length ? $inline : $this; $this.siblings( '.ui-datepicker-append' ).remove(); // Remove appended text - options.onSelect = function () { + options.onSelect = function() { $this.trigger( 'change' ); - }; - options.beforeShow = function ( i ) { + } + options.beforeShow = function( i ) { if ( $( i ).prop( 'readonly' ) ) { return false; } - }; + } if ( $timestamp.length ) { options.onClose = options.onSelect = function () { @@ -41,7 +36,7 @@ } ); } - if ( !$inline.length ) { + if ( ! $inline.length ) { $this.removeClass( 'hasDatepicker' ).datetimepicker( options ); return; } @@ -49,7 +44,7 @@ options.altField = '#' + $this.attr( 'id' ); $this.on( 'keydown', _.debounce( function () { // if val is empty, return to allow empty datepicker input. - if ( !$this.val() ) { + if ( ! $this.val() ) { return; } $picker @@ -83,9 +78,9 @@ // Set language if available function setTimeI18n() { if ( $.timepicker.regional.hasOwnProperty( i18n.locale ) ) { - $.timepicker.setDefaults( $.timepicker.regional[ i18n.locale ] ); + $.timepicker.setDefaults( $.timepicker.regional[i18n.locale] ); } else if ( $.timepicker.regional.hasOwnProperty( i18n.localeShort ) ) { - $.timepicker.setDefaults( $.timepicker.regional[ i18n.localeShort ] ); + $.timepicker.setDefaults( $.timepicker.regional[i18n.localeShort] ); } } diff --git a/modules/meta-box/js/image-select.js b/modules/meta-box/js/image-select.js new file mode 100644 index 0000000..6365f8e --- /dev/null +++ b/modules/meta-box/js/image-select.js @@ -0,0 +1,27 @@ +( function ( $, rwmb ) { + 'use strict'; + + function setActiveClass() { + var $this = $( this ), + type = $this.attr( 'type' ), + selected = $this.is( ':checked' ), + $parent = $this.parent(), + $others = $parent.siblings(); + if ( selected ) { + $parent.addClass( 'rwmb-active' ); + if ( type === 'radio' ) { + $others.removeClass( 'rwmb-active' ); + } + } else { + $parent.removeClass( 'rwmb-active' ); + } + } + + function init( e ) { + $( e.target ).find( '.rwmb-image-select input' ).trigger( 'change' ); + } + + rwmb.$document + .on( 'mb_ready', init ) + .on( 'change', '.rwmb-image-select input', setActiveClass ); +} )( jQuery, rwmb ); diff --git a/modules/meta-box/js/time.js b/modules/meta-box/js/time.js index d4ba9e0..8b0335b 100644 --- a/modules/meta-box/js/time.js +++ b/modules/meta-box/js/time.js @@ -5,8 +5,9 @@ * Transform an input into a time picker. */ function transform() { - let $this = $( this ), + var $this = $( this ), options = $this.data( 'options' ), + $inline = $this.siblings( '.rwmb-datetime-inline' ), current = $this.val(); current = formatTime( current ); @@ -21,10 +22,6 @@ } }; - let $inline = $this.siblings( '.rwmb-datetime-inline' ); - if ( !$inline.length ) { - $inline = $this.closest( '.rwmb-input-group' ).siblings( '.rwmb-datetime-inline' ); - } if ( !$inline.length ) { $this.removeClass( 'hasDatepicker' ).timepicker( options ).timepicker( 'setTime', current ); return; diff --git a/modules/meta-box/src/Updater/Checker.php b/modules/meta-box/src/Updater/Checker.php new file mode 100644 index 0000000..8cbb62e --- /dev/null +++ b/modules/meta-box/src/Updater/Checker.php @@ -0,0 +1,182 @@ +option = $option; + } + + public function init() { + add_action( 'init', [ $this, 'enable_update' ], 1 ); + } + + public function enable_update() { + if ( $this->has_extensions() ) { + add_filter( 'pre_set_site_transient_update_plugins', [ $this, 'check_updates' ] ); + add_filter( 'plugins_api', [ $this, 'get_info' ], 10, 3 ); + } + } + + public function has_extensions() { + $extensions = $this->get_extensions(); + return ! empty( $extensions ); + } + + public function get_extensions() { + if ( ! function_exists( 'get_plugins' ) ) { + require_once ABSPATH . 'wp-admin/includes/plugin.php'; + } + + $extensions = [ + 'mb-admin-columns', + 'mb-blocks', + 'mb-core', + 'mb-custom-table', + 'mb-frontend-submission', + 'mb-revision', + 'mb-settings-page', + 'mb-term-meta', + 'mb-user-meta', + 'mb-user-profile', + 'mb-views', + 'meta-box-aio', + 'meta-box-builder', + 'meta-box-columns', + 'meta-box-conditional-logic', + 'meta-box-geolocation', + 'meta-box-group', + 'meta-box-include-exclude', + 'meta-box-show-hide', + 'meta-box-tabs', + 'meta-box-template', + + 'mb-favorite-posts', + 'mb-testimonials', + 'mb-user-avatar', + ]; + $plugins = get_plugins(); + $plugins = array_map( 'dirname', array_keys( $plugins ) ); + + return array_intersect( $extensions, $plugins ); + } + + /** + * Check plugin for updates + * + * @param object $data The plugin update data. + * + * @return mixed + */ + public function check_updates( $data ) { + static $response = null; + + $request = rwmb_request(); + + // Bypass embed plugins via TGMPA. + if ( $request->get( 'tgmpa-update' ) || 'tgmpa-bulk-update' === $request->post( 'action' ) ) { + return $data; + } + + // Make sure to send remote request once. + if ( null === $response ) { + $response = $this->request( 'plugins' ); + } + + if ( empty( $response ) ) { + return $data; + } + + if ( empty( $data ) ) { + $data = new stdClass; + } + if ( ! isset( $data->response ) ) { + $data->response = []; + } + + $plugins = array_filter( $response['data'], [ $this, 'has_update' ] ); + foreach ( $plugins as $plugin ) { + if ( empty( $plugin['package'] ) ) { + $plugin['upgrade_notice'] = __( 'UPDATE UNAVAILABLE! Please enter a valid license key to enable automatic updates.', 'meta-box' ); + } + + $data->response[ $plugin['plugin'] ] = (object) $plugin; + } + + $this->option->update( [ + 'status' => $response['status'], + 'plugins' => array_keys( $plugins ), + ] ); + + return $data; + } + + /** + * Get plugin information + * + * @param object $data The plugin update data. + * @param string $action Request action. + * @param object $args Extra parameters. + * + * @return mixed + */ + public function get_info( $data, $action, $args ) { + $plugins = $this->option->get( 'plugins', [] ); + if ( 'plugin_information' !== $action || ! isset( $args->slug ) || ! in_array( $args->slug, $plugins, true ) ) { + return $data; + } + + $response = $this->request( 'plugin', [ 'product' => $args->slug ] ); + return $response ? (object) $response['data'] : $data; + } + + public function request( $endpoint, $args = [] ) { + $args = wp_parse_args( $args, [ + 'key' => $this->option->get_api_key(), + 'url' => home_url(), + 'force' => false, + ] ); + + // Get from cache first. + $data = compact( 'endpoint', 'args' ); + $cache_key = 'meta_box_' . md5( serialize( $data ) ); + if ( $this->option->is_network_activated() ) { + $cache = get_site_transient( $cache_key ); + } else { + $cache = get_transient( $cache_key ); + } + if ( ! $args['force'] && $cache ) { + return $cache; + } + + $url = $this->api_url . $endpoint; + $request = wp_remote_get( add_query_arg( $args, $url ) ); + $response = wp_remote_retrieve_body( $request ); + $response = json_decode( $response, true ); + + // Cache requests. + if ( $this->option->is_network_activated() ) { + set_site_transient( $cache_key, $response, DAY_IN_SECONDS ); + } else { + set_transient( $cache_key, $response, DAY_IN_SECONDS ); + } + + return $response; + } + + private function has_update( $remote_plugin_data ) { + $slug = $remote_plugin_data['plugin']; + $plugins = get_plugins(); + + if ( empty( $plugins[ $slug ] ) ) { + return false; + } + + $plugin = $plugins[ $slug ]; + return version_compare( $plugin['Version'], $remote_plugin_data['new_version'], '<' ); + } +} diff --git a/modules/meta-box/src/Updater/Notification.php b/modules/meta-box/src/Updater/Notification.php new file mode 100644 index 0000000..53645f4 --- /dev/null +++ b/modules/meta-box/src/Updater/Notification.php @@ -0,0 +1,116 @@ +checker = $checker; + $this->option = $option; + + $this->settings_page = $option->is_network_activated() ? network_admin_url( 'settings.php?page=meta-box-updater' ) : admin_url( 'admin.php?page=meta-box-updater' ); + } + + /** + * Add hooks to show admin notice. + */ + public function init() { + if ( ! $this->checker->has_extensions() ) { + return; + } + + // Show update message on Plugins page. + $extensions = $this->checker->get_extensions(); + foreach ( $extensions as $extension ) { + $file = "{$extension}/{$extension}.php"; + add_action( "in_plugin_update_message-$file", [ $this, 'show_update_message' ], 10, 2 ); + add_filter( "plugin_action_links_$file", [ $this, 'plugin_links' ], 20 ); + } + + $admin_notices_hook = $this->option->is_network_activated() ? 'network_admin_notices' : 'admin_notices'; + add_action( $admin_notices_hook, [ $this, 'notify' ] ); + } + + public function notify() { + $excluded_screens = [ + 'meta-box_page_meta-box-updater', + 'settings_page_meta-box-updater-network', + 'meta-box_page_meta-box-aio', + ]; + $screen = get_current_screen(); + if ( in_array( $screen->id, $excluded_screens, true ) ) { + return; + } + + $messages = [ + // Translators: %1$s - URL to the settings page, %2$s - URL to the pricing page. + 'no_key' => __( 'You have not set your Meta Box license key yet, which means you are missing out on automatic updates and support! Please enter your license key or get a new one here.', 'meta-box' ), + // Translators: %1$s - URL to the settings page, %2$s - URL to the pricing page. + 'invalid' => __( 'Your license key for Meta Box is invalid. Please update your license key or get a new one to enable automatic updates.', 'meta-box' ), + // Translators: %1$s - URL to the settings page, %2$s - URL to the pricing page. + 'error' => __( 'Your license key for Meta Box is invalid. Please update your license key or get a new one to enable automatic updates.', 'meta-box' ), + // Translators: %3$s - URL to the My Account page. + 'expired' => __( 'Your license key for Meta Box is expired. Please renew your license to get automatic updates and premium support.', 'meta-box' ), + ]; + $status = $this->option->get_license_status(); + if ( ! isset( $messages[ $status ] ) ) { + return; + } + + echo '

', wp_kses_post( sprintf( $messages[ $status ], $this->settings_page, 'https://elu.to/mnp', 'https://elu.to/mna' ) ), '

'; + } + + /** + * Show update message on Plugins page. + * + * @param array $plugin_data Plugin data. + * @param object $response Available plugin update data. + */ + public function show_update_message( $plugin_data, $response ) { + // Users have an active license. + if ( ! empty( $response->package ) ) { + return; + } + + $messages = [ + // Translators: %1$s - URL to the settings page, %2$s - URL to the pricing page. + 'no_key' => __( 'Please enter your license key or get a new one here.', 'meta-box' ), + // Translators: %1$s - URL to the settings page, %2$s - URL to the pricing page. + 'invalid' => __( 'Your license key is invalid. Please update your license key or get a new one here.', 'meta-box' ), + // Translators: %1$s - URL to the settings page, %2$s - URL to the pricing page. + 'error' => __( 'Your license key is invalid. Please update your license key or get a new one here.', 'meta-box' ), + // Translators: %3$s - URL to the My Account page. + 'expired' => __( 'Your license key is expired. Please renew your license.', 'meta-box' ), + ]; + $status = $this->option->get_license_status(); + if ( ! isset( $messages[ $status ] ) ) { + return; + } + + echo '
 ' . wp_kses_post( sprintf( $messages[ $status ], $this->settings_page, 'https://elu.to/mnp', 'https://elu.to/mna' ) ); + } + + public function plugin_links( array $links ): array { + $status = $this->option->get_license_status(); + if ( 'active' === $status ) { + return $links; + } + + $text = 'no_key' === $status ? __( 'Activate License', 'meta-box' ) : __( 'Update License', 'meta-box' ); + $links[] = '' . esc_html( $text ) . ''; + + return $links; + } +} diff --git a/modules/meta-box/src/Updater/Option.php b/modules/meta-box/src/Updater/Option.php new file mode 100644 index 0000000..ff4a11a --- /dev/null +++ b/modules/meta-box/src/Updater/Option.php @@ -0,0 +1,59 @@ +is_network_activated() ? get_site_option( $this->option, [] ) : get_option( $this->option, [] ); + + return null === $name ? $option : ( $option[ $name ] ?? $default ); + } + + public function get_api_key() : string { + return defined( 'META_BOX_KEY' ) ? META_BOX_KEY : $this->get( 'api_key', '' ); + } + + public function get_license_status() : string { + return $this->get_api_key() ? $this->get( 'status', 'active' ) : 'no_key'; + } + + /** + * Update the option array. + * + * @param array $option Option value. + */ + public function update( $option ) { + $old_option = (array) $this->get(); + + $option = array_merge( $old_option, $option ); + if ( $this->is_network_activated() ) { + update_site_option( $this->option, $option ); + } else { + update_option( $this->option, $option ); + } + } + + public function is_network_activated() : bool { + if ( ! function_exists( 'is_plugin_active_for_network' ) ) { + require_once ABSPATH . '/wp-admin/includes/plugin.php'; + } + return is_multisite() && is_plugin_active_for_network( 'meta-box/meta-box.php' ); + } +} diff --git a/modules/meta-box/src/Updater/Settings.php b/modules/meta-box/src/Updater/Settings.php new file mode 100644 index 0000000..98ad19b --- /dev/null +++ b/modules/meta-box/src/Updater/Settings.php @@ -0,0 +1,147 @@ +checker = $checker; + $this->option = $option; + $this->fake_api_key = 'Please do not steal this license key'; + } + + public function init() { + // Whether to enable Meta Box menu. Priority 1 makes sure it runs before adding Meta Box menu. + $admin_menu_hook = $this->option->is_network_activated() ? 'network_admin_menu' : 'admin_menu'; + add_action( $admin_menu_hook, [ $this, 'enable_menu' ], 1 ); + } + + public function enable_menu() { + if ( ! $this->checker->has_extensions() ) { + return; + } + + // Enable Meta Box menu only in single site. + if ( ! $this->option->is_network_activated() ) { + add_filter( 'rwmb_admin_menu', '__return_true' ); + } + + // Add submenu. Priority 90 makes it the last sub-menu item. + $admin_menu_hook = $this->option->is_network_activated() ? 'network_admin_menu' : 'admin_menu'; + add_action( $admin_menu_hook, [ $this, 'add_settings_page' ], 90 ); + } + + public function add_settings_page() { + $parent = $this->option->is_network_activated() ? 'settings.php' : 'meta-box'; + $capability = $this->option->is_network_activated() ? 'manage_network_options' : 'manage_options'; + $title = $this->option->is_network_activated() ? esc_html__( 'Meta Box License', 'meta-box' ) : esc_html__( 'License', 'meta-box' ); + $page_hook = add_submenu_page( + $parent, + $title, + $title, + $capability, + 'meta-box-updater', + [ $this, 'render' ] + ); + add_action( "load-{$page_hook}", [ $this, 'save' ] ); + } + + public function render() { + ?> +
+

+

+

+ My Account page on metabox.io website. If you have not purchased any extension yet, please get a new license here.', 'meta-box' ) ), + 'https://elu.to/mua', + 'https://elu.to/mup' + ); + ?> +

+ +
+ + + + + + + +
+ __( 'Your license key is invalid.', 'meta-box' ), + 'error' => __( 'Your license key is invalid.', 'meta-box' ), + 'expired' => __( 'Your license key is expired.', 'meta-box' ), + 'active' => __( 'Your license key is active.', 'meta-box' ), + ]; + $status = $this->option->get_license_status(); + $api_key = 'active' === $status ? $this->fake_api_key : $this->option->get( 'api_key' ); + ?> + + +

+ +
+ + +
+
+ post( 'submit' ) ) { + return; + } + check_admin_referer( 'meta-box' ); + + $option = (array) $request->post( 'meta_box_updater', [] ); + + if ( isset( $option['api_key'] ) && $option['api_key'] === $this->fake_api_key ) { + return; + } + + $status = 'invalid'; + $response = null; + if ( isset( $option['api_key'] ) ) { + $args = [ + 'key' => $option['api_key'], + 'force' => true, + ]; + $response = $this->checker->request( 'status', $args ); + $status = $response['status'] ?? 'invalid'; + } + + if ( empty( $response ) ) { + add_settings_error( '', 'mb-error', __( 'Something wrong with the connection to metabox.io. Please try again later.', 'meta-box' ) ); + } elseif ( 'active' === $status ) { + add_settings_error( '', 'mb-success', __( 'Your license is activated.', 'meta-box' ), 'updated' ); + } elseif ( 'expired' === $status ) { + // Translators: %s - URL to the My Account page. + $message = __( 'License expired. Please renew on the My Account page on metabox.io website.', 'meta-box' ); + $message = wp_kses_post( sprintf( $message, 'https://elu.to/mua' ) ); + + add_settings_error( '', 'mb-expired', $message ); + } else { + // Translators: %1$s - URL to the My Account page, %2$s - URL to the pricing page. + $message = __( 'Invalid license. Please check again or get a new license here.', 'meta-box' ); + $message = wp_kses_post( sprintf( $message, 'https://elu.to/mua', 'https://mup' ) ); + + add_settings_error( '', 'mb-invalid', $message ); + } + + $option['status'] = $status; + + $admin_notices_hook = $this->option->is_network_activated() ? 'network_admin_notices' : 'admin_notices'; + add_action( $admin_notices_hook, 'settings_errors' ); + + $this->option->update( $option ); + } +} diff --git a/vendor/composer/autoload_files.php b/vendor/composer/autoload_files.php index 7a1f8f6..e15c6d7 100644 --- a/vendor/composer/autoload_files.php +++ b/vendor/composer/autoload_files.php @@ -6,7 +6,6 @@ $baseDir = dirname($vendorDir); return array( - '256558b1ddf2fa4366ea7d7602798dd1' => $vendorDir . '/yahnis-elsts/plugin-update-checker/load-v5p5.php', 'bb2ad5156ac7a5ea5170e3032f9986c5' => $baseDir . '/modules/meta-box/meta-box.php', '9195b8cf8e415449278c0c4efa05f57e' => $baseDir . '/modules/mb-acf-migration/mb-acf-migration.php', 'd45d9ba5e80690d08cb8d4c4237b57c3' => $baseDir . '/modules/mb-comment-meta/mb-comment-meta.php', diff --git a/vendor/composer/autoload_static.php b/vendor/composer/autoload_static.php index 303d194..6703db8 100644 --- a/vendor/composer/autoload_static.php +++ b/vendor/composer/autoload_static.php @@ -7,7 +7,6 @@ class ComposerStaticInitff1056f71c6dba41d243124bfd07b96d { public static $files = array ( - '256558b1ddf2fa4366ea7d7602798dd1' => __DIR__ . '/..' . '/yahnis-elsts/plugin-update-checker/load-v5p5.php', 'bb2ad5156ac7a5ea5170e3032f9986c5' => __DIR__ . '/../..' . '/modules/meta-box/meta-box.php', '9195b8cf8e415449278c0c4efa05f57e' => __DIR__ . '/../..' . '/modules/mb-acf-migration/mb-acf-migration.php', 'd45d9ba5e80690d08cb8d4c4237b57c3' => __DIR__ . '/../..' . '/modules/mb-comment-meta/mb-comment-meta.php', diff --git a/vendor/composer/installed.json b/vendor/composer/installed.json index 91a9959..e238f19 100644 --- a/vendor/composer/installed.json +++ b/vendor/composer/installed.json @@ -819,12 +819,12 @@ }, { "name": "wpmetabox/meta-box", - "version": "dev-master", - "version_normalized": "dev-master", + "version": "5.10.5", + "version_normalized": "5.10.5.0", "source": { "type": "git", "url": "git@github.com:wpmetabox/meta-box.git", - "reference": "872dbd07d6ec90b3c5b5530e19e5f724c49797e3" + "reference": "3fa649ba0e8624c71f066a8437a4a47af5998710" }, "require": { "meta-box/support": "dev-master" @@ -832,8 +832,7 @@ "require-dev": { "phpunit/phpunit": "^11.3" }, - "time": "2024-12-23T02:09:08+00:00", - "default-branch": true, + "time": "2024-12-16T06:50:30+00:00", "type": "wordpress-plugin", "extra": { "dev-files": { @@ -1054,59 +1053,6 @@ "source": "https://github.com/wpmetabox/meta-box-text-limiter/tree/master" }, "install-path": "../../modules/text-limiter" - }, - { - "name": "yahnis-elsts/plugin-update-checker", - "version": "v5.5", - "version_normalized": "5.5.0.0", - "source": { - "type": "git", - "url": "https://github.com/YahnisElsts/plugin-update-checker.git", - "reference": "845d65da93bcff31649ede00d9d73b1beadbb7f0" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/YahnisElsts/plugin-update-checker/zipball/845d65da93bcff31649ede00d9d73b1beadbb7f0", - "reference": "845d65da93bcff31649ede00d9d73b1beadbb7f0", - "shasum": "" - }, - "require": { - "ext-json": "*", - "php": ">=5.6.20" - }, - "time": "2024-10-16T14:25:00+00:00", - "type": "library", - "installation-source": "dist", - "autoload": { - "files": [ - "load-v5p5.php" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Yahnis Elsts", - "email": "whiteshadow@w-shadow.com", - "homepage": "https://w-shadow.com/", - "role": "Developer" - } - ], - "description": "A custom update checker for WordPress plugins and themes. Useful if you can't host your plugin in the official WP repository but still want it to support automatic updates.", - "homepage": "https://github.com/YahnisElsts/plugin-update-checker/", - "keywords": [ - "automatic updates", - "plugin updates", - "theme updates", - "wordpress" - ], - "support": { - "issues": "https://github.com/YahnisElsts/plugin-update-checker/issues", - "source": "https://github.com/YahnisElsts/plugin-update-checker/tree/v5.5" - }, - "install-path": "../yahnis-elsts/plugin-update-checker" } ], "dev": true, diff --git a/vendor/composer/installed.php b/vendor/composer/installed.php index 32c27f2..08e598e 100644 --- a/vendor/composer/installed.php +++ b/vendor/composer/installed.php @@ -1,9 +1,9 @@ array( 'name' => '__root__', - 'pretty_version' => 'dev-master', - 'version' => 'dev-master', - 'reference' => 'dd06fed7933b31f3f0a94633eb9c3590100b6d13', + 'pretty_version' => 'dev-main', + 'version' => 'dev-main', + 'reference' => '5f2dc7eef0622809b122e35020a5791b6ca5b483', 'type' => 'library', 'install_path' => __DIR__ . '/../../', 'aliases' => array(), @@ -11,9 +11,9 @@ ), 'versions' => array( '__root__' => array( - 'pretty_version' => 'dev-master', - 'version' => 'dev-master', - 'reference' => 'dd06fed7933b31f3f0a94633eb9c3590100b6d13', + 'pretty_version' => 'dev-main', + 'version' => 'dev-main', + 'reference' => '5f2dc7eef0622809b122e35020a5791b6ca5b483', 'type' => 'library', 'install_path' => __DIR__ . '/../../', 'aliases' => array(), @@ -204,14 +204,12 @@ 'dev_requirement' => false, ), 'wpmetabox/meta-box' => array( - 'pretty_version' => 'dev-master', - 'version' => 'dev-master', - 'reference' => '872dbd07d6ec90b3c5b5530e19e5f724c49797e3', + 'pretty_version' => '5.10.5', + 'version' => '5.10.5.0', + 'reference' => '3fa649ba0e8624c71f066a8437a4a47af5998710', 'type' => 'wordpress-plugin', 'install_path' => __DIR__ . '/../../modules/meta-box', - 'aliases' => array( - 0 => '9999999-dev', - ), + 'aliases' => array(), 'dev_requirement' => false, ), 'wpmetabox/meta-box-beaver-themer-integrator' => array( @@ -247,14 +245,5 @@ ), 'dev_requirement' => false, ), - 'yahnis-elsts/plugin-update-checker' => array( - 'pretty_version' => 'v5.5', - 'version' => '5.5.0.0', - 'reference' => '845d65da93bcff31649ede00d9d73b1beadbb7f0', - 'type' => 'library', - 'install_path' => __DIR__ . '/../yahnis-elsts/plugin-update-checker', - 'aliases' => array(), - 'dev_requirement' => false, - ), ), ); diff --git a/vendor/composer/platform_check.php b/vendor/composer/platform_check.php index 12f8be9..8b379f4 100644 --- a/vendor/composer/platform_check.php +++ b/vendor/composer/platform_check.php @@ -4,8 +4,8 @@ $issues = array(); -if (!(PHP_VERSION_ID >= 50620)) { - $issues[] = 'Your Composer dependencies require a PHP version ">= 5.6.20". You are running ' . PHP_VERSION . '.'; +if (!(PHP_VERSION_ID >= 50600)) { + $issues[] = 'Your Composer dependencies require a PHP version ">= 5.6.0". You are running ' . PHP_VERSION . '.'; } if ($issues) { diff --git a/vendor/yahnis-elsts/plugin-update-checker/Puc/v5/PucFactory.php b/vendor/yahnis-elsts/plugin-update-checker/Puc/v5/PucFactory.php deleted file mode 100644 index a8ebf7e..0000000 --- a/vendor/yahnis-elsts/plugin-update-checker/Puc/v5/PucFactory.php +++ /dev/null @@ -1,10 +0,0 @@ -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/v5p5/DebugBar/Extension.php b/vendor/yahnis-elsts/plugin-update-checker/Puc/v5p5/DebugBar/Extension.php deleted file mode 100644 index 14ab6a2..0000000 --- a/vendor/yahnis-elsts/plugin-update-checker/Puc/v5p5/DebugBar/Extension.php +++ /dev/null @@ -1,199 +0,0 @@ -updateChecker = $updateChecker; - if ( isset($panelClass) ) { - $this->panelClass = $panelClass; - } - - 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_v5_debug_check_now', array($this, 'ajaxCheckNow')); - } - - /** - * Register the PUC Debug Bar panel. - * - * @param array $panels - * @return array - */ - public function addDebugBarPanel($panels) { - if ( $this->updateChecker->userCanInstallUpdates() ) { - $panels[] = new $this->panelClass($this->updateChecker); - } - return $panels; - } - - /** - * Enqueue our Debug Bar scripts and styles. - */ - public function enqueuePanelDependencies() { - wp_enqueue_style( - 'puc-debug-bar-style-v5', - $this->getLibraryUrl("/css/puc-debug-bar.css"), - array('debug-bar'), - '20221008' - ); - - wp_enqueue_script( - 'puc-debug-bar-js-v5', - $this->getLibraryUrl("/js/debug-bar.js"), - array('jquery'), - '20221008' - ); - } - - /** - * Run an update check and output the result. Useful for making sure that - * the update checking process works as expected. - */ - public function ajaxCheckNow() { - //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:"; - //phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_print_r -- For debugging output. - echo '
', esc_html(print_r($update, true)), '
'; - } else { - echo 'No updates found.'; - } - - $errors = $this->updateChecker->getLastRequestApiErrors(); - if ( !empty($errors) ) { - printf('

The update checker encountered %d API error%s.

', count($errors), (count($errors) > 1) ? 's' : ''); - - foreach (array_values($errors) as $num => $item) { - $wpError = $item['error']; - /** @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())); - - if ( isset($item['url']) ) { - printf('
Requested URL:
%s
', esc_html($item['url'])); - } - - if ( isset($item['httpResponse']) ) { - if ( is_wp_error($item['httpResponse']) ) { - $httpError = $item['httpResponse']; - /** @var \WP_Error $httpError */ - printf( - '
WordPress HTTP API error:
%s (%s)
', - esc_html($httpError->get_error_message()), - esc_html($httpError->get_error_code()) - ); - } else { - //Status code. - printf( - '
HTTP status:
%d %s
', - esc_html(wp_remote_retrieve_response_code($item['httpResponse'])), - esc_html(wp_remote_retrieve_response_message($item['httpResponse'])) - ); - - //Headers. - echo '
Response headers:
';
-							foreach (wp_remote_retrieve_headers($item['httpResponse']) as $name => $value) {
-								printf("%s: %s\n", esc_html($name), esc_html($value));
-							}
-							echo '
'; - - //Body. - $body = wp_remote_retrieve_body($item['httpResponse']); - if ( $body === '' ) { - $body = '(Empty response.)'; - } else if ( strlen($body) > self::RESPONSE_BODY_LENGTH_LIMIT ) { - $length = strlen($body); - $body = substr($body, 0, self::RESPONSE_BODY_LENGTH_LIMIT) - . sprintf("\n(Long string truncated. Total length: %d bytes.)", $length); - } - - printf('
Response body:
%s
', esc_html($body)); - } - } - echo '
'; - } - } - - exit; - } - - /** - * Check access permissions and enable error display (for debugging). - */ - protected function preAjaxRequest() { - if ( !$this->updateChecker->userCanInstallUpdates() ) { - die('Access denied'); - } - 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'); - } - - /** - * Remove hooks that were added by this extension. - */ - 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_v5_debug_check_now', array($this, 'ajaxCheckNow')); - } - - /** - * @param string $filePath - * @return string - */ - private function getLibraryUrl($filePath) { - $absolutePath = realpath(dirname(__FILE__) . '/../../../' . ltrim($filePath, '/')); - - //Where is the library located inside the WordPress directory structure? - $absolutePath = PucFactory::normalizePath($absolutePath); - - $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. - return plugins_url(basename($absolutePath), $absolutePath); - } else if ( strpos($absolutePath, $themeDir) === 0 ) { - //It's part of a theme. - $relativePath = substr($absolutePath, strlen($themeDir) + 1); - $template = substr($relativePath, 0, strpos($relativePath, '/')); - $baseUrl = get_theme_root_uri($template); - - if ( !empty($baseUrl) && $relativePath ) { - return $baseUrl . '/' . $relativePath; - } - } - - return ''; - } - } - -endif; diff --git a/vendor/yahnis-elsts/plugin-update-checker/Puc/v5p5/DebugBar/Panel.php b/vendor/yahnis-elsts/plugin-update-checker/Puc/v5p5/DebugBar/Panel.php deleted file mode 100644 index 9a61e74..0000000 --- a/vendor/yahnis-elsts/plugin-update-checker/Puc/v5p5/DebugBar/Panel.php +++ /dev/null @@ -1,186 +0,0 @@ -
'; - - public function __construct($updateChecker) { - $this->updateChecker = $updateChecker; - $title = sprintf( - 'PUC (%s)', - esc_attr($this->updateChecker->getUniqueName('uid')), - $this->updateChecker->slug - ); - parent::__construct($title); - } - - public function render() { - printf( - '
', - esc_attr($this->updateChecker->getUniqueName('debug-bar-panel')), - esc_attr($this->updateChecker->slug), - esc_attr($this->updateChecker->getUniqueName('uid')), - esc_attr(wp_create_nonce('puc-ajax')) - ); - - $this->displayConfiguration(); - $this->displayStatus(); - $this->displayCurrentUpdate(); - - echo '
'; - } - - private function displayConfiguration() { - echo '

Configuration

'; - echo ''; - $this->displayConfigHeader(); - $this->row('Slug', htmlentities($this->updateChecker->slug)); - $this->row('DB option', htmlentities($this->updateChecker->optionName)); - - $requestInfoButton = $this->getMetadataButton(); - $this->row('Metadata URL', htmlentities($this->updateChecker->metadataUrl) . ' ' . $requestInfoButton . $this->responseBox); - - $scheduler = $this->updateChecker->scheduler; - if ( $scheduler->checkPeriod > 0 ) { - $this->row('Automatic checks', 'Every ' . $scheduler->checkPeriod . ' hours'); - } else { - $this->row('Automatic checks', 'Disabled'); - } - - if ( isset($scheduler->throttleRedundantChecks) ) { - if ( $scheduler->throttleRedundantChecks && ($scheduler->checkPeriod > 0) ) { - $this->row( - 'Throttling', - sprintf( - 'Enabled. If an update is already available, check for updates every %1$d hours instead of every %2$d hours.', - $scheduler->throttledCheckPeriod, - $scheduler->checkPeriod - ) - ); - } else { - $this->row('Throttling', 'Disabled'); - } - } - - $this->updateChecker->onDisplayConfiguration($this); - - echo '
'; - } - - protected function displayConfigHeader() { - //Do nothing. This should be implemented in subclasses. - } - - protected function getMetadataButton() { - return ''; - } - - private function displayStatus() { - echo '

Status

'; - echo ''; - $state = $this->updateChecker->getUpdateState(); - $checkButtonId = $this->updateChecker->getUniqueName('check-now-button'); - if ( function_exists('get_submit_button') ) { - $checkNowButton = get_submit_button( - 'Check Now', - 'secondary', - 'puc-check-now-button', - false, - array('id' => $checkButtonId) - ); - } else { - //get_submit_button() is not available in the frontend. Make a button directly. - //It won't look the same without admin styles, but it should still work. - $checkNowButton = sprintf( - '', - esc_attr($checkButtonId), - esc_attr('Check Now') - ); - } - - if ( $state->getLastCheck() > 0 ) { - $this->row('Last check', $this->formatTimeWithDelta($state->getLastCheck()) . ' ' . $checkNowButton . $this->responseBox); - } else { - $this->row('Last check', 'Never'); - } - - $nextCheck = wp_next_scheduled($this->updateChecker->scheduler->getCronHookName()); - $this->row('Next automatic check', $this->formatTimeWithDelta($nextCheck)); - - if ( $state->getCheckedVersion() !== '' ) { - $this->row('Checked version', htmlentities($state->getCheckedVersion())); - $this->row('Cached update', $state->getUpdate()); - } - $this->row('Update checker class', htmlentities(get_class($this->updateChecker))); - echo '
'; - } - - private function displayCurrentUpdate() { - $update = $this->updateChecker->getUpdate(); - if ( $update !== null ) { - echo '

An Update Is Available

'; - echo ''; - $fields = $this->getUpdateFields(); - foreach($fields as $field) { - if ( property_exists($update, $field) ) { - $this->row( - ucwords(str_replace('_', ' ', $field)), - isset($update->$field) ? htmlentities($update->$field) : null - ); - } - } - echo '
'; - } else { - echo '

No updates currently available

'; - } - } - - protected function getUpdateFields() { - return array('version', 'download_url', 'slug',); - } - - private function formatTimeWithDelta($unixTime) { - if ( empty($unixTime) ) { - return 'Never'; - } - - $delta = time() - $unixTime; - $result = human_time_diff(time(), $unixTime); - if ( $delta < 0 ) { - $result = 'after ' . $result; - } else { - $result = $result . ' ago'; - } - $result .= ' (' . $this->formatTimestamp($unixTime) . ')'; - return $result; - } - - private function formatTimestamp($unixTime) { - return gmdate('Y-m-d H:i:s', $unixTime + (get_option('gmt_offset') * 3600)); - } - - 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', - esc_html($name), - //phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- Escaped above. - $value - ); - } - } - -endif; diff --git a/vendor/yahnis-elsts/plugin-update-checker/Puc/v5p5/DebugBar/PluginExtension.php b/vendor/yahnis-elsts/plugin-update-checker/Puc/v5p5/DebugBar/PluginExtension.php deleted file mode 100644 index 50972ec..0000000 --- a/vendor/yahnis-elsts/plugin-update-checker/Puc/v5p5/DebugBar/PluginExtension.php +++ /dev/null @@ -1,40 +0,0 @@ -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/v5p5/DebugBar/PluginPanel.php b/vendor/yahnis-elsts/plugin-update-checker/Puc/v5p5/DebugBar/PluginPanel.php deleted file mode 100644 index 8bd2dc5..0000000 --- a/vendor/yahnis-elsts/plugin-update-checker/Puc/v5p5/DebugBar/PluginPanel.php +++ /dev/null @@ -1,47 +0,0 @@ -row('Plugin file', htmlentities($this->updateChecker->pluginFile)); - parent::displayConfigHeader(); - } - - protected function getMetadataButton() { - $buttonId = $this->updateChecker->getUniqueName('request-info-button'); - if ( function_exists('get_submit_button') ) { - $requestInfoButton = get_submit_button( - 'Request Info', - 'secondary', - 'puc-request-info-button', - false, - array('id' => $buttonId) - ); - } else { - $requestInfoButton = sprintf( - '', - esc_attr($buttonId), - esc_attr('Request Info') - ); - } - return $requestInfoButton; - } - - protected function getUpdateFields() { - return array_merge( - parent::getUpdateFields(), - array('homepage', 'upgrade_notice', 'tested',) - ); - } - } - -endif; diff --git a/vendor/yahnis-elsts/plugin-update-checker/Puc/v5p5/DebugBar/ThemePanel.php b/vendor/yahnis-elsts/plugin-update-checker/Puc/v5p5/DebugBar/ThemePanel.php deleted file mode 100644 index e9c99ff..0000000 --- a/vendor/yahnis-elsts/plugin-update-checker/Puc/v5p5/DebugBar/ThemePanel.php +++ /dev/null @@ -1,25 +0,0 @@ -row('Theme directory', htmlentities($this->updateChecker->directoryName)); - parent::displayConfigHeader(); - } - - protected function getUpdateFields() { - return array_merge(parent::getUpdateFields(), array('details_url')); - } - } - -endif; diff --git a/vendor/yahnis-elsts/plugin-update-checker/Puc/v5p5/InstalledPackage.php b/vendor/yahnis-elsts/plugin-update-checker/Puc/v5p5/InstalledPackage.php deleted file mode 100644 index 54521c8..0000000 --- a/vendor/yahnis-elsts/plugin-update-checker/Puc/v5p5/InstalledPackage.php +++ /dev/null @@ -1,105 +0,0 @@ -updateChecker = $updateChecker; - } - - /** - * Get the currently installed version of the plugin or theme. - * - * @return string|null Version number. - */ - abstract public function getInstalledVersion(); - - /** - * Get the full path of the plugin or theme directory (without a trailing slash). - * - * @return string - */ - abstract public function getAbsoluteDirectoryPath(); - - /** - * Check whether a regular file exists in the package's directory. - * - * @param string $relativeFileName File name relative to the package directory. - * @return bool - */ - public function fileExists($relativeFileName) { - return is_file( - $this->getAbsoluteDirectoryPath() - . DIRECTORY_SEPARATOR - . ltrim($relativeFileName, '/\\') - ); - } - - /* ------------------------------------------------------------------- - * File header parsing - * ------------------------------------------------------------------- - */ - - /** - * Parse plugin or theme metadata from the header comment. - * - * This is basically a simplified version of the get_file_data() function from /wp-includes/functions.php. - * It's intended as a utility for subclasses that detect updates by parsing files in a VCS. - * - * @param string|null $content File contents. - * @return string[] - */ - public function getFileHeader($content) { - $content = (string)$content; - - //WordPress only looks at the first 8 KiB of the file, so we do the same. - $content = substr($content, 0, 8192); - //Normalize line endings. - $content = str_replace("\r", "\n", $content); - - $headers = $this->getHeaderNames(); - $results = array(); - foreach ($headers as $field => $name) { - $success = preg_match('/^[ \t\/*#@]*' . preg_quote($name, '/') . ':(.*)$/mi', $content, $matches); - - if ( ($success === 1) && $matches[1] ) { - $value = $matches[1]; - if ( function_exists('_cleanup_header_comment') ) { - $value = _cleanup_header_comment($value); - } - $results[$field] = $value; - } else { - $results[$field] = ''; - } - } - - return $results; - } - - /** - * @return array Format: ['HeaderKey' => 'Header Name'] - */ - abstract protected function getHeaderNames(); - - /** - * Get the value of a specific plugin or theme header. - * - * @param string $headerName - * @return string Either the value of the header, or an empty string if the header doesn't exist. - */ - abstract public function getHeaderValue($headerName); - - } -endif; diff --git a/vendor/yahnis-elsts/plugin-update-checker/Puc/v5p5/Metadata.php b/vendor/yahnis-elsts/plugin-update-checker/Puc/v5p5/Metadata.php deleted file mode 100644 index 54426cd..0000000 --- a/vendor/yahnis-elsts/plugin-update-checker/Puc/v5p5/Metadata.php +++ /dev/null @@ -1,162 +0,0 @@ - - */ - protected $extraProperties = array(); - - /** - * Create an instance of this class from a JSON document. - * - * @abstract - * @param string $json - * @return self - */ - public static function fromJson($json) { - throw new LogicException('The ' . __METHOD__ . ' method must be implemented by subclasses'); - } - - /** - * @param string $json - * @param self $target - * @return bool - */ - protected static function createFromJson($json, $target) { - /** @var \StdClass $apiResponse */ - $apiResponse = json_decode($json); - if ( empty($apiResponse) || !is_object($apiResponse) ){ - $errorMessage = "Failed to parse update metadata. Try validating your .json file with https://jsonlint.com/"; - do_action('puc_api_error', new WP_Error('puc-invalid-json', $errorMessage)); - //phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_trigger_error -- For plugin developers. - trigger_error(esc_html($errorMessage), E_USER_NOTICE); - return false; - } - - $valid = $target->validateMetadata($apiResponse); - if ( is_wp_error($valid) ){ - do_action('puc_api_error', $valid); - //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; - } - - foreach(get_object_vars($apiResponse) as $key => $value){ - $target->$key = $value; - } - - return true; - } - - /** - * No validation by default! Subclasses should check that the required fields are present. - * - * @param \StdClass $apiResponse - * @return bool|\WP_Error - */ - protected function validateMetadata($apiResponse) { - return true; - } - - /** - * Create a new instance by copying the necessary fields from another object. - * - * @abstract - * @param \StdClass|self $object The source object. - * @return self The new copy. - */ - public static function fromObject($object) { - throw new LogicException('The ' . __METHOD__ . ' method must be implemented by subclasses'); - } - - /** - * Create an instance of StdClass that can later be converted back to an - * update or info container. Useful for serialization and caching, as it - * avoids the "incomplete object" problem if the cached value is loaded - * before this class. - * - * @return \StdClass - */ - public function toStdClass() { - $object = new stdClass(); - $this->copyFields($this, $object); - return $object; - } - - /** - * Transform the metadata into the format used by WordPress core. - * - * @return object - */ - abstract public function toWpFormat(); - - /** - * Copy known fields from one object to another. - * - * @param \StdClass|self $from - * @param \StdClass|self $to - */ - protected function copyFields($from, $to) { - $fields = $this->getFieldNames(); - - if ( property_exists($from, 'slug') && !empty($from->slug) ) { - //Let plugins add extra fields without having to create subclasses. - $fields = apply_filters($this->getPrefixedFilter('retain_fields') . '-' . $from->slug, $fields); - } - - foreach ($fields as $field) { - if ( property_exists($from, $field) ) { - $to->$field = $from->$field; - } - } - } - - /** - * @return string[] - */ - protected function getFieldNames() { - return array(); - } - - /** - * @param string $tag - * @return string - */ - protected function getPrefixedFilter($tag) { - return 'puc_' . $tag; - } - - public function __set($name, $value) { - $this->extraProperties[$name] = $value; - } - - public function __get($name) { - return isset($this->extraProperties[$name]) ? $this->extraProperties[$name] : null; - } - - public function __isset($name) { - return isset($this->extraProperties[$name]); - } - - public function __unset($name) { - unset($this->extraProperties[$name]); - } - } - -endif; diff --git a/vendor/yahnis-elsts/plugin-update-checker/Puc/v5p5/OAuthSignature.php b/vendor/yahnis-elsts/plugin-update-checker/Puc/v5p5/OAuthSignature.php deleted file mode 100644 index 848aa15..0000000 --- a/vendor/yahnis-elsts/plugin-update-checker/Puc/v5p5/OAuthSignature.php +++ /dev/null @@ -1,102 +0,0 @@ -consumerKey = $consumerKey; - $this->consumerSecret = $consumerSecret; - } - - /** - * Sign a URL using OAuth 1.0. - * - * @param string $url The URL to be signed. It may contain query parameters. - * @param string $method HTTP method such as "GET", "POST" and so on. - * @return string The signed URL. - */ - public function sign($url, $method = 'GET') { - $parameters = array(); - - //Parse query parameters. - $query = wp_parse_url($url, PHP_URL_QUERY); - if ( !empty($query) ) { - parse_str($query, $parsedParams); - if ( is_array($parsedParams) ) { - $parameters = $parsedParams; - } - //Remove the query string from the URL. We'll replace it later. - $url = substr($url, 0, strpos($url, '?')); - } - - $parameters = array_merge( - $parameters, - array( - 'oauth_consumer_key' => $this->consumerKey, - 'oauth_nonce' => $this->nonce(), - 'oauth_signature_method' => 'HMAC-SHA1', - 'oauth_timestamp' => time(), - 'oauth_version' => '1.0', - ) - ); - unset($parameters['oauth_signature']); - - //Parameters must be sorted alphabetically before signing. - ksort($parameters); - - //The most complicated part of the request - generating the signature. - //The string to sign contains the HTTP method, the URL path, and all of - //our query parameters. Everything is URL encoded. Then we concatenate - //them with ampersands into a single string to hash. - $encodedVerb = urlencode($method); - $encodedUrl = urlencode($url); - $encodedParams = urlencode(http_build_query($parameters, '', '&')); - - $stringToSign = $encodedVerb . '&' . $encodedUrl . '&' . $encodedParams; - - //Since we only have one OAuth token (the consumer secret) we only have - //to use it as our HMAC key. However, we still have to append an & to it - //as if we were using it with additional tokens. - $secret = urlencode($this->consumerSecret) . '&'; - - //The signature is a hash of the consumer key and the base string. Note - //that we have to get the raw output from hash_hmac and base64 encode - //the binary data result. - $parameters['oauth_signature'] = base64_encode(hash_hmac('sha1', $stringToSign, $secret, true)); - - return ($url . '?' . http_build_query($parameters)); - } - - /** - * Generate a random nonce. - * - * @return string - */ - private function nonce() { - $mt = microtime(); - - $rand = null; - if ( is_callable('random_bytes') ) { - try { - $rand = random_bytes(16); - } catch (\Exception $ex) { - //Fall back to mt_rand (below). - } - } - if ( $rand === null ) { - //phpcs:ignore WordPress.WP.AlternativeFunctions.rand_mt_rand - $rand = function_exists('wp_rand') ? wp_rand() : mt_rand(); - } - - return md5($mt . '_' . $rand); - } - } - -endif; diff --git a/vendor/yahnis-elsts/plugin-update-checker/Puc/v5p5/Plugin/Package.php b/vendor/yahnis-elsts/plugin-update-checker/Puc/v5p5/Plugin/Package.php deleted file mode 100644 index 67b3ca1..0000000 --- a/vendor/yahnis-elsts/plugin-update-checker/Puc/v5p5/Plugin/Package.php +++ /dev/null @@ -1,188 +0,0 @@ -pluginAbsolutePath = $pluginAbsolutePath; - $this->pluginFile = plugin_basename($this->pluginAbsolutePath); - - parent::__construct($updateChecker); - - //Clear the version number cache when something - anything - is upgraded or WP clears the update cache. - add_filter('upgrader_post_install', array($this, 'clearCachedVersion')); - add_action('delete_site_transient_update_plugins', array($this, 'clearCachedVersion')); - } - - public function getInstalledVersion() { - if ( isset($this->cachedInstalledVersion) ) { - return $this->cachedInstalledVersion; - } - - $pluginHeader = $this->getPluginHeader(); - if ( isset($pluginHeader['Version']) ) { - $this->cachedInstalledVersion = $pluginHeader['Version']; - return $pluginHeader['Version']; - } else { - //This can happen if the filename points to something that is not a plugin. - $this->updateChecker->triggerError( - sprintf( - "Cannot read the Version header for '%s'. The filename is incorrect or is not a plugin.", - $this->updateChecker->pluginFile - ), - E_USER_WARNING - ); - return null; - } - } - - /** - * Clear the cached plugin version. This method can be set up as a filter (hook) and will - * return the filter argument unmodified. - * - * @param mixed $filterArgument - * @return mixed - */ - public function clearCachedVersion($filterArgument = null) { - $this->cachedInstalledVersion = null; - return $filterArgument; - } - - public function getAbsoluteDirectoryPath() { - return dirname($this->pluginAbsolutePath); - } - - /** - * Get the value of a specific plugin or theme header. - * - * @param string $headerName - * @param string $defaultValue - * @return string Either the value of the header, or $defaultValue if the header doesn't exist or is empty. - */ - public function getHeaderValue($headerName, $defaultValue = '') { - $headers = $this->getPluginHeader(); - if ( isset($headers[$headerName]) && ($headers[$headerName] !== '') ) { - return $headers[$headerName]; - } - return $defaultValue; - } - - protected function getHeaderNames() { - return array( - 'Name' => 'Plugin Name', - 'PluginURI' => 'Plugin URI', - 'Version' => 'Version', - 'Description' => 'Description', - 'Author' => 'Author', - 'AuthorURI' => 'Author URI', - 'TextDomain' => 'Text Domain', - 'DomainPath' => 'Domain Path', - 'Network' => 'Network', - - //The newest WordPress version that this plugin requires or has been tested with. - //We support several different formats for compatibility with other libraries. - 'Tested WP' => 'Tested WP', - 'Requires WP' => 'Requires WP', - 'Tested up to' => 'Tested up to', - 'Requires at least' => 'Requires at least', - ); - } - - /** - * Get the translated plugin title. - * - * @return string - */ - public function getPluginTitle() { - $title = ''; - $header = $this->getPluginHeader(); - if ( $header && !empty($header['Name']) && isset($header['TextDomain']) ) { - $title = translate($header['Name'], $header['TextDomain']); - } - return $title; - } - - /** - * Get plugin's metadata from its file header. - * - * @return array - */ - public function getPluginHeader() { - if ( !is_file($this->pluginAbsolutePath) ) { - //This can happen if the plugin filename is wrong. - $this->updateChecker->triggerError( - sprintf( - "Can't to read the plugin header for '%s'. The file does not exist.", - $this->updateChecker->pluginFile - ), - E_USER_WARNING - ); - return array(); - } - - if ( !function_exists('get_plugin_data') ) { - require_once(ABSPATH . '/wp-admin/includes/plugin.php'); - } - return get_plugin_data($this->pluginAbsolutePath, false, false); - } - - public function removeHooks() { - remove_filter('upgrader_post_install', array($this, 'clearCachedVersion')); - remove_action('delete_site_transient_update_plugins', array($this, 'clearCachedVersion')); - } - - /** - * Check if the plugin file is inside the mu-plugins directory. - * - * @return bool - */ - public function isMuPlugin() { - static $cachedResult = null; - - if ( $cachedResult === null ) { - if ( !defined('WPMU_PLUGIN_DIR') || !is_string(WPMU_PLUGIN_DIR) ) { - $cachedResult = false; - return $cachedResult; - } - - //Convert both paths to the canonical form before comparison. - $muPluginDir = realpath(WPMU_PLUGIN_DIR); - $pluginPath = realpath($this->pluginAbsolutePath); - //If realpath() fails, just normalize the syntax instead. - if (($muPluginDir === false) || ($pluginPath === false)) { - $muPluginDir = PucFactory::normalizePath(WPMU_PLUGIN_DIR); - $pluginPath = PucFactory::normalizePath($this->pluginAbsolutePath); - } - - $cachedResult = (strpos($pluginPath, $muPluginDir) === 0); - } - - return $cachedResult; - } - } - -endif; diff --git a/vendor/yahnis-elsts/plugin-update-checker/Puc/v5p5/Plugin/PluginInfo.php b/vendor/yahnis-elsts/plugin-update-checker/Puc/v5p5/Plugin/PluginInfo.php deleted file mode 100644 index 83ce17b..0000000 --- a/vendor/yahnis-elsts/plugin-update-checker/Puc/v5p5/Plugin/PluginInfo.php +++ /dev/null @@ -1,136 +0,0 @@ -sections = (array)$instance->sections; - $instance->icons = (array)$instance->icons; - - return $instance; - } - - /** - * Very, very basic validation. - * - * @param \StdClass $apiResponse - * @return bool|\WP_Error - */ - protected function validateMetadata($apiResponse) { - if ( - !isset($apiResponse->name, $apiResponse->version) - || empty($apiResponse->name) - || empty($apiResponse->version) - ) { - return new \WP_Error( - 'puc-invalid-metadata', - "The plugin metadata file does not contain the required 'name' and/or 'version' keys." - ); - } - return true; - } - - - /** - * Transform plugin info into the format used by the native WordPress.org API - * - * @return object - */ - public function toWpFormat(){ - $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. - $sameFormat = array( - 'name', 'slug', 'version', 'requires', 'tested', 'rating', 'upgrade_notice', - 'num_ratings', 'downloaded', 'active_installs', 'homepage', 'last_updated', - 'requires_php', - ); - foreach($sameFormat as $field){ - if ( isset($this->$field) ) { - $info->$field = $this->$field; - } else { - $info->$field = null; - } - } - - //Other fields need to be renamed and/or transformed. - $info->download_link = $this->download_url; - $info->author = $this->getFormattedAuthor(); - $info->sections = array_merge(array('description' => ''), $this->sections); - - if ( !empty($this->banners) ) { - //WP expects an array with two keys: "high" and "low". Both are optional. - //Docs: https://wordpress.org/plugins/about/faq/#banners - $info->banners = is_object($this->banners) ? get_object_vars($this->banners) : $this->banners; - $info->banners = array_intersect_key($info->banners, array('high' => true, 'low' => true)); - } - - return $info; - } - - protected function getFormattedAuthor() { - if ( !empty($this->author_homepage) ){ - /** @noinspection HtmlUnknownTarget */ - return sprintf('%s', $this->author_homepage, $this->author); - } - return $this->author; - } - } - -endif; diff --git a/vendor/yahnis-elsts/plugin-update-checker/Puc/v5p5/Plugin/Ui.php b/vendor/yahnis-elsts/plugin-update-checker/Puc/v5p5/Plugin/Ui.php deleted file mode 100644 index ccc5279..0000000 --- a/vendor/yahnis-elsts/plugin-update-checker/Puc/v5p5/Plugin/Ui.php +++ /dev/null @@ -1,294 +0,0 @@ -updateChecker = $updateChecker; - $this->manualCheckErrorTransient = $this->updateChecker->getUniqueName('manual_check_errors'); - - add_action('admin_init', array($this, 'onAdminInit')); - } - - public function onAdminInit() { - if ( $this->updateChecker->userCanInstallUpdates() ) { - $this->handleManualCheck(); - - add_filter('plugin_row_meta', array($this, 'addViewDetailsLink'), 10, 3); - add_filter('plugin_row_meta', array($this, 'addCheckForUpdatesLink'), 10, 2); - add_action('all_admin_notices', array($this, 'displayManualCheckResult')); - } - } - - /** - * Add a "View Details" link to the plugin row in the "Plugins" page. By default, - * the new link will appear before the "Visit plugin site" link (if present). - * - * You can change the link text by using the "puc_view_details_link-$slug" filter. - * Returning an empty string from the filter will disable the link. - * - * You can change the position of the link using the - * "puc_view_details_link_position-$slug" filter. - * Returning 'before' or 'after' will place the link immediately before/after - * the "Visit plugin site" link. - * Returning 'append' places the link after any existing links at the time of the hook. - * Returning 'replace' replaces the "Visit plugin site" link. - * Returning anything else disables the link when there is a "Visit plugin site" link. - * - * If there is no "Visit plugin site" link 'append' is always used! - * - * @param array $pluginMeta Array of meta links. - * @param string $pluginFile - * @param array $pluginData Array of plugin header data. - * @return array - */ - public function addViewDetailsLink($pluginMeta, $pluginFile, $pluginData = array()) { - if ( $this->isMyPluginFile($pluginFile) && !isset($pluginData['slug']) ) { - $linkText = apply_filters($this->updateChecker->getUniqueName('view_details_link'), __('View details')); - if ( !empty($linkText) ) { - $viewDetailsLinkPosition = 'append'; - - //Find the "Visit plugin site" link (if present). - $visitPluginSiteLinkIndex = count($pluginMeta) - 1; - if ( $pluginData['PluginURI'] ) { - $escapedPluginUri = esc_url($pluginData['PluginURI']); - foreach ($pluginMeta as $linkIndex => $existingLink) { - if ( strpos($existingLink, $escapedPluginUri) !== false ) { - $visitPluginSiteLinkIndex = $linkIndex; - $viewDetailsLinkPosition = apply_filters( - $this->updateChecker->getUniqueName('view_details_link_position'), - 'before' - ); - break; - } - } - } - - $viewDetailsLink = sprintf('%s', - esc_url(network_admin_url('plugin-install.php?tab=plugin-information&plugin=' . urlencode($this->updateChecker->slug) . - '&TB_iframe=true&width=600&height=550')), - esc_attr(sprintf(__('More information about %s'), $pluginData['Name'])), - esc_attr($pluginData['Name']), - $linkText - ); - switch ($viewDetailsLinkPosition) { - case 'before': - array_splice($pluginMeta, $visitPluginSiteLinkIndex, 0, $viewDetailsLink); - break; - case 'after': - array_splice($pluginMeta, $visitPluginSiteLinkIndex + 1, 0, $viewDetailsLink); - break; - case 'replace': - $pluginMeta[$visitPluginSiteLinkIndex] = $viewDetailsLink; - break; - case 'append': - default: - $pluginMeta[] = $viewDetailsLink; - break; - } - } - } - return $pluginMeta; - } - - /** - * Add a "Check for updates" link to the plugin row in the "Plugins" page. By default, - * the new link will appear after the "Visit plugin site" link if present, otherwise - * after the "View plugin details" link. - * - * You can change the link text by using the "puc_manual_check_link-$slug" filter. - * Returning an empty string from the filter will disable the link. - * - * @param array $pluginMeta Array of meta links. - * @param string $pluginFile - * @return array - */ - public function addCheckForUpdatesLink($pluginMeta, $pluginFile) { - if ( $this->isMyPluginFile($pluginFile) ) { - $linkUrl = wp_nonce_url( - add_query_arg( - array( - 'puc_check_for_updates' => 1, - 'puc_slug' => $this->updateChecker->slug, - ), - self_admin_url('plugins.php') - ), - 'puc_check_for_updates' - ); - - $linkText = apply_filters( - $this->updateChecker->getUniqueName('manual_check_link'), - __('Check for updates', 'plugin-update-checker') - ); - if ( !empty($linkText) ) { - /** @noinspection HtmlUnknownTarget */ - $pluginMeta[] = sprintf('%s', esc_attr($linkUrl), $linkText); - } - } - return $pluginMeta; - } - - protected function isMyPluginFile($pluginFile) { - return ($pluginFile == $this->updateChecker->pluginFile) - || (!empty($this->updateChecker->muPluginFile) && ($pluginFile == $this->updateChecker->muPluginFile)); - } - - /** - * Check for updates when the user clicks the "Check for updates" link. - * - * @see self::addCheckForUpdatesLink() - * - * @return void - */ - public function handleManualCheck() { - $shouldCheck = - isset($_GET['puc_check_for_updates'], $_GET['puc_slug']) - && $_GET['puc_slug'] == $this->updateChecker->slug - && check_admin_referer('puc_check_for_updates'); - - if ( $shouldCheck ) { - $update = $this->updateChecker->checkForUpdates(); - $status = ($update === null) ? 'no_update' : 'update_available'; - $lastRequestApiErrors = $this->updateChecker->getLastRequestApiErrors(); - - if ( ($update === null) && !empty($lastRequestApiErrors) ) { - //Some errors are not critical. For example, if PUC tries to retrieve the readme.txt - //file from GitHub and gets a 404, that's an API error, but it doesn't prevent updates - //from working. Maybe the plugin simply doesn't have a readme. - //Let's only show important errors. - $foundCriticalErrors = false; - $questionableErrorCodes = array( - 'puc-github-http-error', - 'puc-gitlab-http-error', - 'puc-bitbucket-http-error', - ); - - foreach ($lastRequestApiErrors as $item) { - $wpError = $item['error']; - /** @var \WP_Error $wpError */ - if ( !in_array($wpError->get_error_code(), $questionableErrorCodes) ) { - $foundCriticalErrors = true; - break; - } - } - - if ( $foundCriticalErrors ) { - $status = 'error'; - set_site_transient($this->manualCheckErrorTransient, $lastRequestApiErrors, 60); - } - } - - wp_redirect(add_query_arg( - array( - 'puc_update_check_result' => $status, - 'puc_slug' => $this->updateChecker->slug, - ), - self_admin_url('plugins.php') - )); - exit; - } - } - - /** - * Display the results of a manual update check. - * - * @see self::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 = sanitize_key($_GET['puc_update_check_result']); - $title = $this->updateChecker->getInstalledPackage()->getPluginTitle(); - $noticeClass = 'updated notice-success'; - $details = ''; - - if ( $status == 'no_update' ) { - $message = sprintf(_x('The %s plugin is up to date.', 'the plugin title', 'plugin-update-checker'), $title); - } else if ( $status == 'update_available' ) { - $message = sprintf(_x('A new version of the %s plugin is available.', 'the plugin title', 'plugin-update-checker'), $title); - } else if ( $status === 'error' ) { - $message = sprintf(_x('Could not determine if updates are available for %s.', 'the plugin title', 'plugin-update-checker'), $title); - $noticeClass = 'error notice-error'; - - $details = $this->formatManualCheckErrors(get_site_transient($this->manualCheckErrorTransient)); - delete_site_transient($this->manualCheckErrorTransient); - } else { - $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
', - 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 - } - - /** - * Format the list of errors that were thrown during an update check. - * - * @param array $errors - * @return string - */ - protected function formatManualCheckErrors($errors) { - if ( empty($errors) ) { - return ''; - } - $output = ''; - - $showAsList = count($errors) > 1; - if ( $showAsList ) { - $output .= '
    '; - $formatString = '
  1. %1$s %2$s
  2. '; - } else { - $formatString = '

    %1$s %2$s

    '; - } - foreach ($errors as $item) { - $wpError = $item['error']; - /** @var \WP_Error $wpError */ - $output .= sprintf( - $formatString, - esc_html($wpError->get_error_message()), - esc_html($wpError->get_error_code()) - ); - } - if ( $showAsList ) { - $output .= '
'; - } - - return $output; - } - - public function removeHooks() { - remove_action('admin_init', array($this, 'onAdminInit')); - remove_filter('plugin_row_meta', array($this, 'addViewDetailsLink'), 10); - remove_filter('plugin_row_meta', array($this, 'addCheckForUpdatesLink'), 10); - remove_action('all_admin_notices', array($this, 'displayManualCheckResult')); - } - } -endif; diff --git a/vendor/yahnis-elsts/plugin-update-checker/Puc/v5p5/Plugin/Update.php b/vendor/yahnis-elsts/plugin-update-checker/Puc/v5p5/Plugin/Update.php deleted file mode 100644 index b1c6f62..0000000 --- a/vendor/yahnis-elsts/plugin-update-checker/Puc/v5p5/Plugin/Update.php +++ /dev/null @@ -1,116 +0,0 @@ -copyFields($object, $update); - return $update; - } - - /** - * @return string[] - */ - protected function getFieldNames() { - return array_merge(parent::getFieldNames(), self::$extraFields); - } - - /** - * Transform the update into the format used by WordPress native plugin API. - * - * @return object - */ - public function toWpFormat() { - $update = parent::toWpFormat(); - - $update->id = $this->id; - $update->url = $this->homepage; - $update->tested = $this->tested; - $update->requires_php = $this->requires_php; - $update->plugin = $this->filename; - - if ( !empty($this->upgrade_notice) ) { - $update->upgrade_notice = $this->upgrade_notice; - } - - if ( !empty($this->icons) && is_array($this->icons) ) { - //This should be an array with up to 4 keys: 'svg', '1x', '2x' and 'default'. - //Docs: https://developer.wordpress.org/plugins/wordpress-org/plugin-assets/#plugin-icons - $icons = array_intersect_key( - $this->icons, - array('svg' => true, '1x' => true, '2x' => true, 'default' => true) - ); - if ( !empty($icons) ) { - $update->icons = $icons; - - //It appears that the 'default' icon isn't used anywhere in WordPress 4.9, - //but lets set it just in case a future release needs it. - if ( !isset($update->icons['default']) ) { - $update->icons['default'] = current($update->icons); - } - } - } - - return $update; - } - } - -endif; diff --git a/vendor/yahnis-elsts/plugin-update-checker/Puc/v5p5/Plugin/UpdateChecker.php b/vendor/yahnis-elsts/plugin-update-checker/Puc/v5p5/Plugin/UpdateChecker.php deleted file mode 100644 index 0b194fd..0000000 --- a/vendor/yahnis-elsts/plugin-update-checker/Puc/v5p5/Plugin/UpdateChecker.php +++ /dev/null @@ -1,425 +0,0 @@ -pluginAbsolutePath = $pluginFile; - $this->pluginFile = plugin_basename($this->pluginAbsolutePath); - $this->muPluginFile = $muPluginFile; - - //If no slug is specified, use the name of the main plugin file as the slug. - //For example, 'my-cool-plugin/cool-plugin.php' becomes 'cool-plugin'. - if ( empty($slug) ){ - $slug = basename($this->pluginFile, '.php'); - } - - //Plugin slugs must be unique. - $slugCheckFilter = 'puc_is_slug_in_use-' . $slug; - $slugUsedBy = apply_filters($slugCheckFilter, false); - if ( $slugUsedBy ) { - $this->triggerError(sprintf( - 'Plugin slug "%s" is already in use by %s. Slugs must be unique.', - $slug, - $slugUsedBy - ), E_USER_ERROR); - } - add_filter($slugCheckFilter, array($this, 'getAbsolutePath')); - - parent::__construct($metadataUrl, dirname($this->pluginFile), $slug, $checkPeriod, $optionName); - - //Backwards compatibility: If the plugin is a mu-plugin but no $muPluginFile is specified, assume - //it's the same as $pluginFile given that it's not in a subdirectory (WP only looks in the base dir). - if ( (strpbrk($this->pluginFile, '/\\') === false) && $this->isUnknownMuPlugin() ) { - $this->muPluginFile = $this->pluginFile; - } - - //To prevent a crash during plugin uninstallation, remove updater hooks when the user removes the plugin. - //Details: https://github.com/YahnisElsts/plugin-update-checker/issues/138#issuecomment-335590964 - add_action('uninstall_' . $this->pluginFile, array($this, 'removeHooks')); - - $this->extraUi = new Ui($this); - } - - /** - * Create an instance of the scheduler. - * - * @param int $checkPeriod - * @return Scheduler - */ - protected function createScheduler($checkPeriod) { - $scheduler = new Scheduler($this, $checkPeriod, array('load-plugins.php')); - register_deactivation_hook($this->pluginFile, array($scheduler, 'removeUpdaterCron')); - return $scheduler; - } - - /** - * Install the hooks required to run periodic update checks and inject update info - * into WP data structures. - * - * @return void - */ - protected function installHooks(){ - //Override requests for plugin information - add_filter('plugins_api', array($this, 'injectInfo'), 20, 3); - - parent::installHooks(); - } - - /** - * Remove update checker hooks. - * - * The intent is to prevent a fatal error that can happen if the plugin has an uninstall - * hook. During uninstallation, WP includes the main plugin file (which creates a PUC instance), - * the uninstall hook runs, WP deletes the plugin files and then updates some transients. - * If PUC hooks are still around at this time, they could throw an error while trying to - * autoload classes from files that no longer exist. - * - * The "site_transient_{$transient}" filter is the main problem here, but let's also remove - * most other PUC hooks to be safe. - * - * @internal - */ - public function removeHooks() { - parent::removeHooks(); - $this->extraUi->removeHooks(); - $this->package->removeHooks(); - - remove_filter('plugins_api', array($this, 'injectInfo'), 20); - } - - /** - * Retrieve plugin info from the configured API endpoint. - * - * @uses wp_remote_get() - * - * @param array $queryArgs Additional query arguments to append to the request. Optional. - * @return PluginInfo - */ - public function requestInfo($queryArgs = array()) { - list($pluginInfo, $result) = $this->requestMetadata( - PluginInfo::class, - 'request_info', - $queryArgs - ); - - if ( $pluginInfo !== null ) { - /** @var PluginInfo $pluginInfo */ - $pluginInfo->filename = $this->pluginFile; - $pluginInfo->slug = $this->slug; - } - - $pluginInfo = apply_filters($this->getUniqueName('request_info_result'), $pluginInfo, $result); - return $pluginInfo; - } - - /** - * Retrieve the latest update (if any) from the configured API endpoint. - * - * @uses UpdateChecker::requestInfo() - * - * @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() - //and transforms the result accordingly. - $pluginInfo = $this->requestInfo(array('checking_for_updates' => '1')); - if ( $pluginInfo === null ){ - return null; - } - $update = Update::fromPluginInfo($pluginInfo); - - $update = $this->filterUpdateResult($update); - - return $update; - } - - /** - * Intercept plugins_api() calls that request information about our plugin and - * use the configured API endpoint to satisfy them. - * - * @see plugins_api() - * - * @param mixed $result - * @param string $action - * @param array|object $args - * @return mixed - */ - public function injectInfo($result, $action = null, $args = null){ - $relevant = ($action == 'plugin_information') && isset($args->slug) && ( - ($args->slug == $this->slug) || ($args->slug == dirname($this->pluginFile)) - ); - if ( !$relevant ) { - return $result; - } - - $pluginInfo = $this->requestInfo(); - $this->fixSupportedWordpressVersion($pluginInfo); - - $pluginInfo = apply_filters($this->getUniqueName('pre_inject_info'), $pluginInfo); - if ( $pluginInfo ) { - return $pluginInfo->toWpFormat(); - } - - return $result; - } - - protected function shouldShowUpdates() { - //No update notifications for mu-plugins unless explicitly enabled. The MU plugin file - //is usually different from the main plugin file so the update wouldn't show up properly anyway. - return !$this->isUnknownMuPlugin(); - } - - /** - * @param \stdClass|null $updates - * @param \stdClass $updateToAdd - * @return \stdClass - */ - protected function addUpdateToList($updates, $updateToAdd) { - if ( $this->package->isMuPlugin() ) { - //WP does not support automatic update installation for mu-plugins, but we can - //still display a notice. - $updateToAdd->package = null; - } - return parent::addUpdateToList($updates, $updateToAdd); - } - - /** - * @param \stdClass|null $updates - * @return \stdClass|null - */ - protected function removeUpdateFromList($updates) { - $updates = parent::removeUpdateFromList($updates); - if ( !empty($this->muPluginFile) && isset($updates, $updates->response) ) { - unset($updates->response[$this->muPluginFile]); - } - return $updates; - } - - /** - * For plugins, the update array is indexed by the plugin filename relative to the "plugins" - * directory. Example: "plugin-name/plugin.php". - * - * @return string - */ - protected function getUpdateListKey() { - if ( $this->package->isMuPlugin() ) { - return $this->muPluginFile; - } - return $this->pluginFile; - } - - protected function getNoUpdateItemFields() { - return array_merge( - parent::getNoUpdateItemFields(), - array( - 'id' => $this->pluginFile, - 'slug' => $this->slug, - 'plugin' => $this->pluginFile, - 'icons' => array(), - 'banners' => array(), - 'banners_rtl' => array(), - 'tested' => '', - 'compatibility' => new \stdClass(), - ) - ); - } - - /** - * Alias for isBeingUpgraded(). - * - * @deprecated - * @param \WP_Upgrader|null $upgrader The upgrader that's performing the current update. - * @return bool - */ - public function isPluginBeingUpgraded($upgrader = null) { - return $this->isBeingUpgraded($upgrader); - } - - /** - * Is there an update being installed for this plugin, right now? - * - * @param \WP_Upgrader|null $upgrader - * @return bool - */ - public function isBeingUpgraded($upgrader = null) { - return $this->upgraderStatus->isPluginBeingUpgraded($this->pluginFile, $upgrader); - } - - /** - * Get the details of the currently available update, if any. - * - * If no updates are available, or if the last known update version is below or equal - * to the currently installed version, this method will return NULL. - * - * Uses cached update data. To retrieve update information straight from - * the metadata URL, call requestUpdate() instead. - * - * @return Update|null - */ - public function getUpdate() { - $update = parent::getUpdate(); - if ( isset($update) ) { - /** @var Update $update */ - $update->filename = $this->pluginFile; - } - return $update; - } - - /** - * Get the translated plugin title. - * - * @deprecated - * @return string - */ - public function getPluginTitle() { - return $this->package->getPluginTitle(); - } - - /** - * Check if the current user has the required permissions to install updates. - * - * @return bool - */ - public function userCanInstallUpdates() { - return current_user_can('update_plugins'); - } - - /** - * Check if the plugin file is inside the mu-plugins directory. - * - * @deprecated - * @return bool - */ - protected function isMuPlugin() { - return $this->package->isMuPlugin(); - } - - /** - * MU plugins are partially supported, but only when we know which file in mu-plugins - * corresponds to this plugin. - * - * @return bool - */ - protected function isUnknownMuPlugin() { - return empty($this->muPluginFile) && $this->package->isMuPlugin(); - } - - /** - * Get absolute path to the main plugin file. - * - * @return string - */ - public function getAbsolutePath() { - return $this->pluginAbsolutePath; - } - - /** - * Register a callback for filtering query arguments. - * - * The callback function should take one argument - an associative array of query arguments. - * It should return a modified array of query arguments. - * - * @uses add_filter() This method is a convenience wrapper for add_filter(). - * - * @param callable $callback - * @return void - */ - public function addQueryArgFilter($callback){ - $this->addFilter('request_info_query_args', $callback); - } - - /** - * Register a callback for filtering arguments passed to wp_remote_get(). - * - * The callback function should take one argument - an associative array of arguments - - * and return a modified array or arguments. See the WP documentation on wp_remote_get() - * for details on what arguments are available and how they work. - * - * @uses add_filter() This method is a convenience wrapper for add_filter(). - * - * @param callable $callback - * @return void - */ - public function addHttpRequestArgFilter($callback) { - $this->addFilter('request_info_options', $callback); - } - - /** - * Register a callback for filtering the plugin info retrieved from the external API. - * - * The callback function should take two arguments. If the plugin info was retrieved - * successfully, the first argument passed will be an instance of PluginInfo. Otherwise, - * it will be NULL. The second argument will be the corresponding return value of - * wp_remote_get (see WP docs for details). - * - * The callback function should return a new or modified instance of PluginInfo or NULL. - * - * @uses add_filter() This method is a convenience wrapper for add_filter(). - * - * @param callable $callback - * @return void - */ - public function addResultFilter($callback) { - $this->addFilter('request_info_result', $callback, 10, 2); - } - - protected function createDebugBarExtension() { - return new DebugBar\PluginExtension($this); - } - - /** - * Create a package instance that represents this plugin or theme. - * - * @return InstalledPackage - */ - protected function createInstalledPackage() { - return new Package($this->pluginAbsolutePath, $this); - } - - /** - * @return Package - */ - public function getInstalledPackage() { - return $this->package; - } - } - -endif; diff --git a/vendor/yahnis-elsts/plugin-update-checker/Puc/v5p5/PucFactory.php b/vendor/yahnis-elsts/plugin-update-checker/Puc/v5p5/PucFactory.php deleted file mode 100644 index 3494951..0000000 --- a/vendor/yahnis-elsts/plugin-update-checker/Puc/v5p5/PucFactory.php +++ /dev/null @@ -1,362 +0,0 @@ - '', - 'slug' => '', - 'checkPeriod' => 12, - 'optionName' => '', - 'muPluginFile' => '', - ); - $args = array_merge($defaults, array_intersect_key($args, $defaults)); - extract($args, EXTR_SKIP); - - //Check for the service URI - if ( empty($metadataUrl) ) { - $metadataUrl = self::getServiceURI($fullPath); - } - - return self::buildUpdateChecker($metadataUrl, $fullPath, $slug, $checkPeriod, $optionName, $muPluginFile); - } - - /** - * Create a new instance of the update checker. - * - * This method automatically detects if you're using it for a plugin or a theme and chooses - * the appropriate implementation for your update source (JSON file, GitHub, BitBucket, etc). - * - * @see UpdateChecker::__construct - * - * @param string $metadataUrl The URL of the metadata file, a GitHub repository, or another supported update source. - * @param string $fullPath Full path to the main plugin file or to the theme directory. - * @param string $slug Custom slug. Defaults to the name of the main plugin file or the theme directory. - * @param int $checkPeriod How often to check for updates (in hours). - * @param string $optionName Where to store bookkeeping info about update checks. - * @param string $muPluginFile The plugin filename relative to the mu-plugins directory. - * @return Plugin\UpdateChecker|Theme\UpdateChecker|Vcs\BaseChecker - */ - public static function buildUpdateChecker($metadataUrl, $fullPath, $slug = '', $checkPeriod = 12, $optionName = '', $muPluginFile = '') { - $fullPath = self::normalizePath($fullPath); - $id = null; - - //Plugin or theme? - $themeDirectory = self::getThemeDirectoryName($fullPath); - if ( self::isPluginFile($fullPath) ) { - $type = 'Plugin'; - $id = $fullPath; - } else if ( $themeDirectory !== null ) { - $type = 'Theme'; - $id = $themeDirectory; - } else { - throw new \RuntimeException(sprintf( - 'The update checker cannot determine if "%s" is a plugin or a theme. ' . - 'This is a bug. Please contact the PUC developer.', - htmlentities($fullPath) - )); - } - - //Which hosting service does the URL point to? - $service = self::getVcsService($metadataUrl); - - $apiClass = null; - if ( empty($service) ) { - //The default is to get update information from a remote JSON file. - $checkerClass = $type . '\\UpdateChecker'; - } else { - //You can also use a VCS repository like GitHub. - $checkerClass = 'Vcs\\' . $type . 'UpdateChecker'; - $apiClass = $service . 'Api'; - } - - $checkerClass = self::getCompatibleClassVersion($checkerClass); - if ( $checkerClass === null ) { - //phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_trigger_error - trigger_error( - esc_html(sprintf( - 'PUC %s does not support updates for %ss %s', - self::$latestCompatibleVersion, - strtolower($type), - $service ? ('hosted on ' . $service) : 'using JSON metadata' - )), - E_USER_ERROR - ); - } - - if ( !isset($apiClass) ) { - //Plain old update checker. - return new $checkerClass($metadataUrl, $id, $slug, $checkPeriod, $optionName, $muPluginFile); - } else { - //VCS checker + an API client. - $apiClass = self::getCompatibleClassVersion($apiClass); - if ( $apiClass === null ) { - //phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_trigger_error - trigger_error(esc_html(sprintf( - 'PUC %s does not support %s', - self::$latestCompatibleVersion, - $service - )), E_USER_ERROR); - } - - return new $checkerClass( - new $apiClass($metadataUrl), - $id, - $slug, - $checkPeriod, - $optionName, - $muPluginFile - ); - } - } - - /** - * - * 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.5) - * - * @param string $path Path to normalize. - * @return string Normalized path. - */ - public static function normalizePath($path) { - if ( function_exists('wp_normalize_path') ) { - return wp_normalize_path($path); - } - $path = str_replace('\\', '/', $path); - $path = preg_replace('|(?<=.)/+|', '/', $path); - if ( substr($path, 1, 1) === ':' ) { - $path = ucfirst($path); - } - return $path; - } - - /** - * Check if the path points to a plugin file. - * - * @param string $absolutePath Normalized path. - * @return bool - */ - protected static function isPluginFile($absolutePath) { - //Is the file inside the "plugins" or "mu-plugins" directory? - $pluginDir = self::normalizePath(WP_PLUGIN_DIR); - $muPluginDir = self::normalizePath(WPMU_PLUGIN_DIR); - if ( (strpos($absolutePath, $pluginDir) === 0) || (strpos($absolutePath, $muPluginDir) === 0) ) { - return true; - } - - //Is it a file at all? Caution: is_file() can fail if the parent dir. doesn't have the +x permission set. - if ( !is_file($absolutePath) ) { - return false; - } - - //Does it have a valid plugin header? - //This is a last-ditch check for plugins symlinked from outside the WP root. - if ( function_exists('get_file_data') ) { - $headers = get_file_data($absolutePath, array('Name' => 'Plugin Name'), 'plugin'); - return !empty($headers['Name']); - } - - return false; - } - - /** - * Get the name of the theme's directory from a full path to a file inside that directory. - * E.g. "/abc/public_html/wp-content/themes/foo/whatever.php" => "foo". - * - * Note that subdirectories are currently not supported. For example, - * "/xyz/wp-content/themes/my-theme/includes/whatever.php" => NULL. - * - * @param string $absolutePath Normalized path. - * @return string|null Directory name, or NULL if the path doesn't point to a theme. - */ - protected static function getThemeDirectoryName($absolutePath) { - if ( is_file($absolutePath) ) { - $absolutePath = dirname($absolutePath); - } - - if ( file_exists($absolutePath . '/style.css') ) { - return basename($absolutePath); - } - return null; - } - - /** - * Get the service URI from the file header. - * - * @param string $fullPath - * @return string - */ - private static function getServiceURI($fullPath) { - //Look for the URI - if ( is_readable($fullPath) ) { - $seek = array( - 'github' => 'GitHub URI', - 'gitlab' => 'GitLab URI', - 'bucket' => 'BitBucket URI', - ); - $seek = apply_filters('puc_get_source_uri', $seek); - $data = get_file_data($fullPath, $seek); - foreach ($data as $key => $uri) { - if ( $uri ) { - return $uri; - } - } - } - - //URI was not found so throw an error. - throw new \RuntimeException( - sprintf('Unable to locate URI in header of "%s"', htmlentities($fullPath)) - ); - } - - /** - * Get the name of the hosting service that the URL points to. - * - * @param string $metadataUrl - * @return string|null - */ - private static function getVcsService($metadataUrl) { - $service = null; - - //Which hosting service does the URL point to? - $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". - $repoRegex = '@^/?([^/]+?)/([^/#?&]+?)/?$@'; - if ( $host === 'gitlab.com' ) { - $repoRegex = '@^/?(?:[^/#?&]++/){1,20}(?:[^/#?&]++)/?$@'; - } - if ( preg_match($repoRegex, $path) ) { - $knownServices = array( - 'github.com' => 'GitHub', - 'bitbucket.org' => 'BitBucket', - 'gitlab.com' => 'GitLab', - ); - if ( isset($knownServices[$host]) ) { - $service = $knownServices[$host]; - } - } - - return apply_filters('puc_get_vcs_service', $service, $host, $path, $metadataUrl); - } - - /** - * Get the latest version of the specified class that has the same major version number - * as this factory class. - * - * @param string $class Partial class name. - * @return string|null Full class name. - */ - protected static function getCompatibleClassVersion($class) { - if ( isset(self::$classVersions[$class][self::$latestCompatibleVersion]) ) { - return self::$classVersions[$class][self::$latestCompatibleVersion]; - } - return null; - } - - /** - * Get the specific class name for the latest available version of a class. - * - * @param string $class - * @return null|string - */ - public static function getLatestClassVersion($class) { - if ( !self::$sorted ) { - self::sortVersions(); - } - - if ( isset(self::$classVersions[$class]) ) { - return reset(self::$classVersions[$class]); - } else { - return null; - } - } - - /** - * Sort available class versions in descending order (i.e. newest first). - */ - protected static function sortVersions() { - foreach ( self::$classVersions as $class => $versions ) { - uksort($versions, array(__CLASS__, 'compareVersions')); - self::$classVersions[$class] = $versions; - } - self::$sorted = true; - } - - protected static function compareVersions($a, $b) { - return -version_compare($a, $b); - } - - /** - * Register a version of a class. - * - * @access private This method is only for internal use by the library. - * - * @param string $generalClass Class name without version numbers, e.g. 'PluginUpdateChecker'. - * @param string $versionedClass Actual class name, e.g. 'PluginUpdateChecker_1_2'. - * @param string $version Version number, e.g. '1.2'. - */ - public static function addVersion($generalClass, $versionedClass, $version) { - if ( empty(self::$myMajorVersion) ) { - $lastNamespaceSegment = substr(__NAMESPACE__, strrpos(__NAMESPACE__, '\\') + 1); - self::$myMajorVersion = substr(ltrim($lastNamespaceSegment, 'v'), 0, 1); - } - - //Store the greatest version number that matches our major version. - $components = explode('.', $version); - if ( $components[0] === self::$myMajorVersion ) { - - if ( - empty(self::$latestCompatibleVersion) - || version_compare($version, self::$latestCompatibleVersion, '>') - ) { - self::$latestCompatibleVersion = $version; - } - - } - - if ( !isset(self::$classVersions[$generalClass]) ) { - self::$classVersions[$generalClass] = array(); - } - self::$classVersions[$generalClass][$version] = $versionedClass; - self::$sorted = false; - } - } - -endif; diff --git a/vendor/yahnis-elsts/plugin-update-checker/Puc/v5p5/Scheduler.php b/vendor/yahnis-elsts/plugin-update-checker/Puc/v5p5/Scheduler.php deleted file mode 100644 index e51624e..0000000 --- a/vendor/yahnis-elsts/plugin-update-checker/Puc/v5p5/Scheduler.php +++ /dev/null @@ -1,300 +0,0 @@ -updateChecker = $updateChecker; - $this->checkPeriod = $checkPeriod; - - //Set up the periodic update checks - $this->cronHook = $this->updateChecker->getUniqueName('cron_check_updates'); - if ( $this->checkPeriod > 0 ){ - - //Trigger the check via Cron. - //Try to use one of the default schedules if possible as it's less likely to conflict - //with other plugins and their custom schedules. - $defaultSchedules = array( - 1 => 'hourly', - 12 => 'twicedaily', - 24 => 'daily', - ); - if ( array_key_exists($this->checkPeriod, $defaultSchedules) ) { - $scheduleName = $defaultSchedules[$this->checkPeriod]; - } else { - //Use a custom cron schedule. - $scheduleName = 'every' . $this->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. - $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 - ); - wp_schedule_event($firstCheckTime, $scheduleName, $this->cronHook); - } - add_action($this->cronHook, array($this, 'maybeCheckForUpdates')); - - //In case Cron is disabled or unreliable, we also manually trigger - //the periodic checks while the user is browsing the Dashboard. - add_action( 'admin_init', array($this, 'maybeCheckForUpdates') ); - - //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) { - add_action($hook, array($this, 'maybeCheckForUpdates')); - } - //This hook fires after a bulk update is complete. - add_action('upgrader_process_complete', array($this, 'removeHooksIfLibraryGone'), 1, 0); - add_action('upgrader_process_complete', array($this, 'upgraderProcessComplete'), 11, 2); - - } else { - //Periodic checks are disabled. - wp_clear_scheduled_hook($this->cronHook); - } - } - - /** - * Remove all hooks if this version of PUC has been deleted or overwritten. - * - * Callback for the "upgrader_process_complete" action. - */ - public function removeHooksIfLibraryGone() { - //Cancel all further actions if the current version of PUC has been deleted or overwritten - //by a different version during the upgrade. If we try to do anything more in that situation, - //we could trigger a fatal error by trying to autoload a deleted class. - clearstatcache(); - if ( !file_exists(__FILE__) ) { - $this->removeHooks(); - $this->updateChecker->removeHooks(); - } - } - - /** - * Runs upon the WP action upgrader_process_complete. - * - * 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 array $upgradeInfo extra information about the upgrade - */ - public function upgraderProcessComplete( - /** @noinspection PhpUnusedParameterInspection */ - $upgrader, $upgradeInfo - ) { - //Sanity check and limitation to relevant types. - if ( - !is_array($upgradeInfo) || !isset($upgradeInfo['type'], $upgradeInfo['action']) - || 'update' !== $upgradeInfo['action'] || !in_array($upgradeInfo['type'], array('plugin', 'theme')) - ) { - return; - } - - //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, Theme\UpdateChecker::class) ) { - if ( 'theme' !== $upgradeInfo['type'] || !isset($upgradeInfo['themes']) ) { - return; - } - - //Letting too many things going through for checks is not a real problem, so we compare widely. - if ( !in_array( - strtolower($this->updateChecker->directoryName), - array_map('strtolower', $upgradeInfo['themes']) - ) ) { - return; - } - } - - if ( is_a($this->updateChecker, Plugin\UpdateChecker::class) ) { - if ( 'plugin' !== $upgradeInfo['type'] || !isset($upgradeInfo['plugins']) ) { - return; - } - - //Themes pass in directory names in the information array, but plugins use the relative plugin path. - if ( !in_array( - strtolower($this->updateChecker->directoryName), - array_map('dirname', array_map('strtolower', $upgradeInfo['plugins'])) - ) ) { - return; - } - } - - $this->maybeCheckForUpdates(); - } - - /** - * Check for updates if the configured check interval has already elapsed. - * Will use a shorter check interval on certain admin pages like "Dashboard -> Updates" or when doing cron. - * - * You can override the default behaviour by using the "puc_check_now-$slug" filter. - * The filter callback will be passed three parameters: - * - Current decision. TRUE = check updates now, FALSE = don't check now. - * - Last check time as a Unix timestamp. - * - Configured check period in hours. - * Return TRUE to check for updates immediately, or FALSE to cancel. - * - * This method is declared public because it's a hook callback. Calling it directly is not recommended. - */ - public function maybeCheckForUpdates() { - if ( empty($this->checkPeriod) ){ - return; - } - - $state = $this->updateChecker->getUpdateState(); - $shouldCheck = ($state->timeSinceLastCheck() >= $this->getEffectiveCheckPeriod()); - - if ( $shouldCheck ) { - //Sanity check: Do not proceed if one of the critical classes is missing. - //That can happen - theoretically and extremely rarely - if maybeCheckForUpdates() - //is called before the old version of our plugin has been fully deleted, or - //called from an independent AJAX request during deletion. - if ( !( - class_exists(Utils::class) - && class_exists(Metadata::class) - && class_exists(Plugin\Update::class) - && class_exists(Theme\Update::class) - ) ) { - return; - } - } - - //Let plugin authors substitute their own algorithm. - $shouldCheck = apply_filters( - $this->updateChecker->getUniqueName('check_now'), - $shouldCheck, - $state->getLastCheck(), - $this->checkPeriod - ); - - if ( $shouldCheck ) { - $this->updateChecker->checkForUpdates(); - } - } - - /** - * Calculate the actual check period based on the current status and environment. - * - * @return int Check period in seconds. - */ - protected function getEffectiveCheckPeriod() { - $currentFilter = current_filter(); - if ( in_array($currentFilter, array('load-update-core.php', 'upgrader_process_complete')) ) { - //Check more often when the user visits "Dashboard -> Updates" or does a bulk update. - $period = 60; - } else if ( in_array($currentFilter, $this->hourlyCheckHooks) ) { - //Also check more often on /wp-admin/update.php and the "Plugins" or "Themes" page. - $period = 3600; - } else if ( $this->throttleRedundantChecks && ($this->updateChecker->getUpdate() !== null) ) { - //Check less frequently if it's already known that an update is available. - $period = $this->throttledCheckPeriod * 3600; - } else if ( defined('DOING_CRON') && constant('DOING_CRON') ) { - //WordPress cron schedules are not exact, so let's do an update check even - //if slightly less than $checkPeriod hours have elapsed since the last check. - $cronFuzziness = 20 * 60; - $period = $this->checkPeriod * 3600 - $cronFuzziness; - } else { - $period = $this->checkPeriod * 3600; - } - - return $period; - } - - /** - * Add our custom schedule to the array of Cron schedules used by WP. - * - * @param array $schedules - * @return array - */ - public function _addCustomSchedule($schedules) { - if ( $this->checkPeriod && ($this->checkPeriod > 0) ){ - $scheduleName = 'every' . $this->checkPeriod . 'hours'; - $schedules[$scheduleName] = array( - 'interval' => $this->checkPeriod * 3600, - 'display' => sprintf('Every %d hours', $this->checkPeriod), - ); - } - return $schedules; - } - - /** - * Remove the scheduled cron event that the library uses to check for updates. - * - * @return void - */ - public function removeUpdaterCron() { - wp_clear_scheduled_hook($this->cronHook); - } - - /** - * Get the name of the update checker's WP-cron hook. Mostly useful for debugging. - * - * @return string - */ - public function getCronHookName() { - return $this->cronHook; - } - - /** - * Remove most hooks added by the scheduler. - */ - public function removeHooks() { - remove_filter('cron_schedules', array($this, '_addCustomSchedule')); - remove_action('admin_init', array($this, 'maybeCheckForUpdates')); - remove_action('load-update-core.php', array($this, 'maybeCheckForUpdates')); - - if ( $this->cronHook !== null ) { - remove_action($this->cronHook, array($this, 'maybeCheckForUpdates')); - } - if ( !empty($this->hourlyCheckHooks) ) { - foreach ($this->hourlyCheckHooks as $hook) { - remove_action($hook, array($this, 'maybeCheckForUpdates')); - } - } - } - } - -endif; diff --git a/vendor/yahnis-elsts/plugin-update-checker/Puc/v5p5/StateStore.php b/vendor/yahnis-elsts/plugin-update-checker/Puc/v5p5/StateStore.php deleted file mode 100644 index b3dac76..0000000 --- a/vendor/yahnis-elsts/plugin-update-checker/Puc/v5p5/StateStore.php +++ /dev/null @@ -1,214 +0,0 @@ -optionName = $optionName; - } - - /** - * Get time elapsed since the last update check. - * - * If there are no recorded update checks, this method returns a large arbitrary number - * (i.e. time since the Unix epoch). - * - * @return int Elapsed time in seconds. - */ - public function timeSinceLastCheck() { - $this->lazyLoad(); - return time() - $this->lastCheck; - } - - /** - * @return int - */ - public function getLastCheck() { - $this->lazyLoad(); - return $this->lastCheck; - } - - /** - * Set the time of the last update check to the current timestamp. - * - * @return $this - */ - public function setLastCheckToNow() { - $this->lazyLoad(); - $this->lastCheck = time(); - return $this; - } - - /** - * @return null|Update - */ - public function getUpdate() { - $this->lazyLoad(); - return $this->update; - } - - /** - * @param Update|null $update - * @return $this - */ - public function setUpdate(Update $update = null) { - $this->lazyLoad(); - $this->update = $update; - return $this; - } - - /** - * @return string - */ - public function getCheckedVersion() { - $this->lazyLoad(); - return $this->checkedVersion; - } - - /** - * @param string $version - * @return $this - */ - public function setCheckedVersion($version) { - $this->lazyLoad(); - $this->checkedVersion = strval($version); - return $this; - } - - /** - * Get translation updates. - * - * @return array - */ - public function getTranslations() { - $this->lazyLoad(); - if ( isset($this->update, $this->update->translations) ) { - return $this->update->translations; - } - return array(); - } - - /** - * Set translation updates. - * - * @param array $translationUpdates - */ - public function setTranslations($translationUpdates) { - $this->lazyLoad(); - if ( isset($this->update) ) { - $this->update->translations = $translationUpdates; - $this->save(); - } - } - - public function save() { - $state = new \stdClass(); - - $state->lastCheck = $this->lastCheck; - $state->checkedVersion = $this->checkedVersion; - - if ( isset($this->update)) { - $state->update = $this->update->toStdClass(); - - $updateClass = get_class($this->update); - $state->updateClass = $updateClass; - $prefix = $this->getLibPrefix(); - if ( Utils::startsWith($updateClass, $prefix) ) { - $state->updateBaseClass = substr($updateClass, strlen($prefix)); - } - } - - update_site_option($this->optionName, $state); - $this->isLoaded = true; - } - - /** - * @return $this - */ - public function lazyLoad() { - if ( !$this->isLoaded ) { - $this->load(); - } - return $this; - } - - protected function load() { - $this->isLoaded = true; - - $state = get_site_option($this->optionName, null); - - if ( - !is_object($state) - //Sanity check: If the Utils class is missing, the plugin is probably in the process - //of being deleted (e.g. the old version gets deleted during an update). - || !class_exists(Utils::class) - ) { - $this->lastCheck = 0; - $this->checkedVersion = ''; - $this->update = null; - return; - } - - $this->lastCheck = intval(Utils::get($state, 'lastCheck', 0)); - $this->checkedVersion = Utils::get($state, 'checkedVersion', ''); - $this->update = null; - - if ( isset($state->update) ) { - //This mess is due to the fact that the want the update class from this version - //of the library, not the version that saved the update. - - $updateClass = null; - if ( isset($state->updateBaseClass) ) { - $updateClass = $this->getLibPrefix() . $state->updateBaseClass; - } else if ( isset($state->updateClass) ) { - $updateClass = $state->updateClass; - } - - $factory = array($updateClass, 'fromObject'); - if ( ($updateClass !== null) && is_callable($factory) ) { - $this->update = call_user_func($factory, $state->update); - } - } - } - - public function delete() { - delete_site_option($this->optionName); - - $this->lastCheck = 0; - $this->checkedVersion = ''; - $this->update = null; - } - - private function getLibPrefix() { - //This assumes that the current class is at the top of the versioned namespace. - return __NAMESPACE__ . '\\'; - } - } - -endif; diff --git a/vendor/yahnis-elsts/plugin-update-checker/Puc/v5p5/Theme/Package.php b/vendor/yahnis-elsts/plugin-update-checker/Puc/v5p5/Theme/Package.php deleted file mode 100644 index 7180229..0000000 --- a/vendor/yahnis-elsts/plugin-update-checker/Puc/v5p5/Theme/Package.php +++ /dev/null @@ -1,69 +0,0 @@ -stylesheet = $stylesheet; - $this->theme = wp_get_theme($this->stylesheet); - - parent::__construct($updateChecker); - } - - public function getInstalledVersion() { - return $this->theme->get('Version'); - } - - public function getAbsoluteDirectoryPath() { - if ( method_exists($this->theme, 'get_stylesheet_directory') ) { - return $this->theme->get_stylesheet_directory(); //Available since WP 3.4. - } - return get_theme_root($this->stylesheet) . '/' . $this->stylesheet; - } - - /** - * Get the value of a specific plugin or theme header. - * - * @param string $headerName - * @param string $defaultValue - * @return string Either the value of the header, or $defaultValue if the header doesn't exist or is empty. - */ - public function getHeaderValue($headerName, $defaultValue = '') { - $value = $this->theme->get($headerName); - if ( ($headerName === false) || ($headerName === '') ) { - return $defaultValue; - } - return $value; - } - - protected function getHeaderNames() { - return array( - 'Name' => 'Theme Name', - 'ThemeURI' => 'Theme URI', - 'Description' => 'Description', - 'Author' => 'Author', - 'AuthorURI' => 'Author URI', - 'Version' => 'Version', - 'Template' => 'Template', - 'Status' => 'Status', - 'Tags' => 'Tags', - 'TextDomain' => 'Text Domain', - 'DomainPath' => 'Domain Path', - ); - } - } - -endif; diff --git a/vendor/yahnis-elsts/plugin-update-checker/Puc/v5p5/Theme/Update.php b/vendor/yahnis-elsts/plugin-update-checker/Puc/v5p5/Theme/Update.php deleted file mode 100644 index dfb8c44..0000000 --- a/vendor/yahnis-elsts/plugin-update-checker/Puc/v5p5/Theme/Update.php +++ /dev/null @@ -1,88 +0,0 @@ - $this->slug, - 'new_version' => $this->version, - 'url' => $this->details_url, - ); - - if ( !empty($this->download_url) ) { - $update['package'] = $this->download_url; - } - - return $update; - } - - /** - * Create a new instance of Theme_Update from its JSON-encoded representation. - * - * @param string $json Valid JSON string representing a theme information object. - * @return self New instance of ThemeUpdate, or NULL on error. - */ - public static function fromJson($json) { - $instance = new self(); - if ( !parent::createFromJson($json, $instance) ) { - return null; - } - return $instance; - } - - /** - * Create a new instance by copying the necessary fields from another object. - * - * @param \StdClass|self $object The source object. - * @return self The new copy. - */ - public static function fromObject($object) { - $update = new self(); - $update->copyFields($object, $update); - return $update; - } - - /** - * Basic validation. - * - * @param \StdClass $apiResponse - * @return bool|\WP_Error - */ - protected function validateMetadata($apiResponse) { - $required = array('version', 'details_url'); - foreach($required as $key) { - if ( !isset($apiResponse->$key) || empty($apiResponse->$key) ) { - return new \WP_Error( - 'tuc-invalid-metadata', - sprintf('The theme metadata is missing the required "%s" key.', $key) - ); - } - } - return true; - } - - protected function getFieldNames() { - return array_merge(parent::getFieldNames(), self::$extraFields); - } - - protected function getPrefixedFilter($tag) { - return parent::getPrefixedFilter($tag) . '_theme'; - } - } - -endif; diff --git a/vendor/yahnis-elsts/plugin-update-checker/Puc/v5p5/Theme/UpdateChecker.php b/vendor/yahnis-elsts/plugin-update-checker/Puc/v5p5/Theme/UpdateChecker.php deleted file mode 100644 index 0851cbd..0000000 --- a/vendor/yahnis-elsts/plugin-update-checker/Puc/v5p5/Theme/UpdateChecker.php +++ /dev/null @@ -1,159 +0,0 @@ -stylesheet = $stylesheet; - - parent::__construct( - $metadataUrl, - $stylesheet, - $customSlug ? $customSlug : $stylesheet, - $checkPeriod, - $optionName - ); - } - - /** - * For themes, the update array is indexed by theme directory name. - * - * @return string - */ - protected function getUpdateListKey() { - return $this->directoryName; - } - - /** - * Retrieve the latest update (if any) from the configured API endpoint. - * - * @return Update|null An instance of Update, or NULL when no updates are available. - */ - public function requestUpdate() { - list($themeUpdate, $result) = $this->requestMetadata(Update::class, 'request_update'); - - if ( $themeUpdate !== null ) { - /** @var Update $themeUpdate */ - $themeUpdate->slug = $this->slug; - } - - $themeUpdate = $this->filterUpdateResult($themeUpdate, $result); - return $themeUpdate; - } - - protected function getNoUpdateItemFields() { - return array_merge( - parent::getNoUpdateItemFields(), - array( - 'theme' => $this->directoryName, - 'requires' => '', - ) - ); - } - - public function userCanInstallUpdates() { - return current_user_can('update_themes'); - } - - /** - * Create an instance of the scheduler. - * - * @param int $checkPeriod - * @return Scheduler - */ - protected function createScheduler($checkPeriod) { - 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. - * @return bool - */ - public function isBeingUpgraded($upgrader = null) { - return $this->upgraderStatus->isThemeBeingUpgraded($this->stylesheet, $upgrader); - } - - protected function createDebugBarExtension() { - return new DebugBar\Extension($this, DebugBar\ThemePanel::class); - } - - /** - * Register a callback for filtering query arguments. - * - * The callback function should take one argument - an associative array of query arguments. - * It should return a modified array of query arguments. - * - * @param callable $callback - * @return void - */ - public function addQueryArgFilter($callback){ - $this->addFilter('request_update_query_args', $callback); - } - - /** - * Register a callback for filtering arguments passed to wp_remote_get(). - * - * The callback function should take one argument - an associative array of arguments - - * and return a modified array or arguments. See the WP documentation on wp_remote_get() - * for details on what arguments are available and how they work. - * - * @uses add_filter() This method is a convenience wrapper for add_filter(). - * - * @param callable $callback - * @return void - */ - public function addHttpRequestArgFilter($callback) { - $this->addFilter('request_update_options', $callback); - } - - /** - * Register a callback for filtering theme updates retrieved from the external API. - * - * The callback function should take two arguments. If the theme update was retrieved - * successfully, the first argument passed will be an instance of Theme_Update. Otherwise, - * it will be NULL. The second argument will be the corresponding return value of - * wp_remote_get (see WP docs for details). - * - * The callback function should return a new or modified instance of Theme_Update or NULL. - * - * @uses add_filter() This method is a convenience wrapper for add_filter(). - * - * @param callable $callback - * @return void - */ - public function addResultFilter($callback) { - $this->addFilter('request_update_result', $callback, 10, 2); - } - - /** - * Create a package instance that represents this plugin or theme. - * - * @return InstalledPackage - */ - protected function createInstalledPackage() { - return new Package($this->stylesheet, $this); - } - } - -endif; diff --git a/vendor/yahnis-elsts/plugin-update-checker/Puc/v5p5/Update.php b/vendor/yahnis-elsts/plugin-update-checker/Puc/v5p5/Update.php deleted file mode 100644 index 106d21f..0000000 --- a/vendor/yahnis-elsts/plugin-update-checker/Puc/v5p5/Update.php +++ /dev/null @@ -1,38 +0,0 @@ -slug = $this->slug; - $update->new_version = $this->version; - $update->package = $this->download_url; - - return $update; - } - } - -endif; diff --git a/vendor/yahnis-elsts/plugin-update-checker/Puc/v5p5/UpdateChecker.php b/vendor/yahnis-elsts/plugin-update-checker/Puc/v5p5/UpdateChecker.php deleted file mode 100644 index af5dcd5..0000000 --- a/vendor/yahnis-elsts/plugin-update-checker/Puc/v5p5/UpdateChecker.php +++ /dev/null @@ -1,1141 +0,0 @@ -debugMode = (bool)(constant('WP_DEBUG')); - $this->metadataUrl = $metadataUrl; - $this->directoryName = $directoryName; - $this->slug = !empty($slug) ? $slug : $this->directoryName; - - $this->optionName = $optionName; - if ( empty($this->optionName) ) { - //BC: Initially the library only supported plugin updates and didn't use type prefixes - //in the option name. Lets use the same prefix-less name when possible. - if ( $this->filterSuffix === '' ) { - $this->optionName = 'external_updates-' . $this->slug; - } else { - $this->optionName = $this->getUniqueName('external_updates'); - } - } - - if ( empty($this->translationType) ) { - $this->translationType = $this->componentType; - } - - $this->package = $this->createInstalledPackage(); - $this->scheduler = $this->createScheduler($checkPeriod); - $this->upgraderStatus = new UpgraderStatus(); - $this->updateState = new StateStore($this->optionName); - - if ( did_action('init') ) { - $this->loadTextDomain(); - } else { - add_action('init', array($this, 'loadTextDomain')); - } - - $this->installHooks(); - - if ( ($this->wpCliCheckTrigger === null) && defined('WP_CLI') ) { - $this->wpCliCheckTrigger = new WpCliCheckTrigger($this->componentType, $this->scheduler); - } - } - - /** - * @internal - */ - public function loadTextDomain() { - //We're not using load_plugin_textdomain() or its siblings because figuring out where - //the library is located (plugin, mu-plugin, theme, custom wp-content paths) is messy. - $domain = 'plugin-update-checker'; - $locale = apply_filters( - 'plugin_locale', - (is_admin() && function_exists('get_user_locale')) ? get_user_locale() : get_locale(), - $domain - ); - - $moFile = $domain . '-' . $locale . '.mo'; - $path = realpath(dirname(__FILE__) . '/../../languages'); - - if ($path && file_exists($path)) { - load_textdomain($domain, $path . '/' . $moFile); - } - } - - protected function installHooks() { - //Insert our update info into the update array maintained by WP. - add_filter('site_transient_' . $this->updateTransient, array($this,'injectUpdate')); - - //Insert translation updates into the update list. - add_filter('site_transient_' . $this->updateTransient, array($this, 'injectTranslationUpdates')); - - //Clear translation updates when WP clears the update cache. - //This needs to be done directly because the library doesn't actually remove obsolete plugin updates, - //it just hides them (see getUpdate()). We can't do that with translations - too much disk I/O. - add_action( - 'delete_site_transient_' . $this->updateTransient, - array($this, 'clearCachedTranslationUpdates') - ); - - //Rename the update directory to be the same as the existing directory. - if ( $this->directoryName !== '.' ) { - add_filter('upgrader_source_selection', array($this, 'fixDirectoryName'), 10, 3); - } - - //Allow HTTP requests to the metadata URL even if it's on a local host. - add_filter('http_request_host_is_external', array($this, 'allowMetadataHost'), 10, 2); - - //Potentially exclude information about this entity from core update check requests to api.wordpress.org. - //phpcs:ignore WordPressVIPMinimum.Hooks.RestrictedHooks.http_request_args -- Doesn't modify timeouts. - add_filter('http_request_args', array($this, 'excludeEntityFromWordPressAPI'), 10, 2); - - //DebugBar integration. - if ( did_action('plugins_loaded') ) { - $this->maybeInitDebugBar(); - } else { - add_action('plugins_loaded', array($this, 'maybeInitDebugBar')); - } - } - - /** - * Remove hooks that were added by this update checker instance. - */ - public function removeHooks() { - remove_filter('site_transient_' . $this->updateTransient, array($this,'injectUpdate')); - remove_filter('site_transient_' . $this->updateTransient, array($this, 'injectTranslationUpdates')); - remove_action( - 'delete_site_transient_' . $this->updateTransient, - array($this, 'clearCachedTranslationUpdates') - ); - - remove_filter('upgrader_source_selection', array($this, 'fixDirectoryName'), 10); - remove_filter('http_request_host_is_external', array($this, 'allowMetadataHost'), 10); - remove_filter('http_request_args', array($this, 'excludeEntityFromWordPressAPI')); - remove_action('plugins_loaded', array($this, 'maybeInitDebugBar')); - - remove_action('init', array($this, 'loadTextDomain')); - - if ( $this->scheduler ) { - $this->scheduler->removeHooks(); - } - - if ( $this->debugBarExtension ) { - $this->debugBarExtension->removeHooks(); - } - } - - /** - * Check if the current user has the required permissions to install updates. - * - * @return bool - */ - abstract public function userCanInstallUpdates(); - - /** - * Explicitly allow HTTP requests to the metadata URL. - * - * WordPress has a security feature where the HTTP API will reject all requests that are sent to - * another site hosted on the same server as the current site (IP match), a local host, or a local - * IP, unless the host exactly matches the current site. - * - * This feature is opt-in (at least in WP 4.4). Apparently some people enable it. - * - * That can be a problem when you're developing your plugin and you decide to host the update information - * on the same server as your test site. Update requests will mysteriously fail. - * - * We fix that by adding an exception for the metadata host. - * - * @param bool $allow - * @param string $host - * @return bool - */ - public function allowMetadataHost($allow, $host) { - if ( $this->cachedMetadataHost === 0 ) { - $this->cachedMetadataHost = wp_parse_url($this->metadataUrl, PHP_URL_HOST); - } - - if ( is_string($this->cachedMetadataHost) && (strtolower($host) === strtolower($this->cachedMetadataHost)) ) { - return true; - } - return $allow; - } - - /** - * Create a package instance that represents this plugin or theme. - * - * @return InstalledPackage - */ - abstract protected function createInstalledPackage(); - - /** - * @return InstalledPackage - */ - public function getInstalledPackage() { - return $this->package; - } - - /** - * Create an instance of the scheduler. - * - * This is implemented as a method to make it possible for plugins to subclass the update checker - * and substitute their own scheduler. - * - * @param int $checkPeriod - * @return Scheduler - */ - abstract protected function createScheduler($checkPeriod); - - /** - * Remove information about this plugin or theme from the requests that WordPress core sends - * to api.wordpress.org when checking for updates. - * - * @param array $args - * @param string $url - * @return array - */ - public function excludeEntityFromWordPressAPI($args, $url) { - //Is this an api.wordpress.org update check request? - $parsedUrl = wp_parse_url($url); - if ( !isset($parsedUrl['host']) || (strtolower($parsedUrl['host']) !== 'api.wordpress.org') ) { - return $args; - } - - $typePluralised = $this->componentType . 's'; - $expectedPathPrefix = '/' . $typePluralised . '/update-check/1.'; //e.g. "/plugins/update-check/1.1/" - if ( !isset($parsedUrl['path']) || !Utils::startsWith($parsedUrl['path'], $expectedPathPrefix) ) { - return $args; - } - - //Plugins and themes can disable this feature by using the filter below. - if ( !apply_filters( - $this->getUniqueName('remove_from_default_update_checks'), - true, $this, $args, $url - ) ) { - return $args; - } - - if ( empty($args['body'][$typePluralised]) ) { - return $args; - } - - $reportingItems = json_decode($args['body'][$typePluralised], true); - if ( $reportingItems === null ) { - return $args; - } - - //The list of installed items uses different key formats for plugins and themes. - //Luckily, we can reuse the getUpdateListKey() method here. - $updateListKey = $this->getUpdateListKey(); - if ( isset($reportingItems[$typePluralised][$updateListKey]) ) { - unset($reportingItems[$typePluralised][$updateListKey]); - } - - if ( !empty($reportingItems['active']) ) { - if ( is_array($reportingItems['active']) ) { - foreach ($reportingItems['active'] as $index => $relativePath) { - if ( $relativePath === $updateListKey ) { - unset($reportingItems['active'][$index]); - } - } - //Re-index the array. - $reportingItems['active'] = array_values($reportingItems['active']); - } else if ( $reportingItems['active'] === $updateListKey ) { - //For themes, the "active" field is a string that contains the theme's directory name. - //Pretend that the default theme is active so that we don't reveal the actual theme. - if ( defined('WP_DEFAULT_THEME') ) { - $reportingItems['active'] = WP_DEFAULT_THEME; - } - - //Unfortunately, it doesn't seem to be documented if we can safely remove the "active" - //key. So when we don't know the default theme, we'll just leave it as is. - } - } - - $args['body'][$typePluralised] = wp_json_encode($reportingItems); - return $args; - } - - /** - * Check for updates. The results are stored in the DB option specified in $optionName. - * - * @return Update|null - */ - public function checkForUpdates() { - $installedVersion = $this->getInstalledVersion(); - //Fail silently if we can't find the plugin/theme or read its header. - if ( $installedVersion === null ) { - $this->triggerError( - sprintf('Skipping update check for %s - installed version unknown.', $this->slug), - E_USER_WARNING - ); - return null; - } - - //Start collecting API errors. - $this->lastRequestApiErrors = array(); - add_action('puc_api_error', array($this, 'collectApiErrors'), 10, 4); - - $state = $this->updateState; - $state->setLastCheckToNow() - ->setCheckedVersion($installedVersion) - ->save(); //Save before checking in case something goes wrong - - $state->setUpdate($this->requestUpdate()); - $state->save(); - - //Stop collecting API errors. - remove_action('puc_api_error', array($this, 'collectApiErrors'), 10); - - return $this->getUpdate(); - } - - /** - * Load the update checker state from the DB. - * - * @return StateStore - */ - public function getUpdateState() { - return $this->updateState->lazyLoad(); - } - - /** - * Reset update checker state - i.e. last check time, cached update data and so on. - * - * Call this when your plugin is being uninstalled, or if you want to - * clear the update cache. - */ - public function resetUpdateState() { - $this->updateState->delete(); - } - - /** - * Get the details of the currently available update, if any. - * - * If no updates are available, or if the last known update version is below or equal - * to the currently installed version, this method will return NULL. - * - * Uses cached update data. To retrieve update information straight from - * the metadata URL, call requestUpdate() instead. - * - * @return Update|null - */ - public function getUpdate() { - $update = $this->updateState->getUpdate(); - - //Is there an update available? - if ( isset($update) ) { - //Check if the update is actually newer than the currently installed version. - $installedVersion = $this->getInstalledVersion(); - if ( ($installedVersion !== null) && version_compare($update->version, $installedVersion, '>') ){ - return $update; - } - } - return null; - } - - /** - * Retrieve the latest update (if any) from the configured API endpoint. - * - * Subclasses should run the update through filterUpdateResult before returning it. - * - * @return Update An instance of Update, or NULL when no updates are available. - */ - abstract public function requestUpdate(); - - /** - * Filter the result of a requestUpdate() call. - * - * @template T of Update - * @param T|null $update - * @param array|WP_Error|null $httpResult The value returned by wp_remote_get(), if any. - * @return T - */ - protected function filterUpdateResult($update, $httpResult = null) { - //Let plugins/themes modify the update. - $update = apply_filters($this->getUniqueName('request_update_result'), $update, $httpResult); - - $this->fixSupportedWordpressVersion($update); - - if ( isset($update, $update->translations) ) { - //Keep only those translation updates that apply to this site. - $update->translations = $this->filterApplicableTranslations($update->translations); - } - - return $update; - } - - /** - * The "Tested up to" field in the plugin metadata is supposed to be in the form of "major.minor", - * while WordPress core's list_plugin_updates() expects the $update->tested field to be an exact - * version, e.g. "major.minor.patch", to say it's compatible. In other case it shows - * "Compatibility: Unknown". - * The function mimics how wordpress.org API crafts the "tested" field out of "Tested up to". - * - * @param Metadata|null $update - */ - protected function fixSupportedWordpressVersion(Metadata $update = null) { - if ( !isset($update->tested) || !preg_match('/^\d++\.\d++$/', $update->tested) ) { - return; - } - - $actualWpVersions = array(); - - $wpVersion = $GLOBALS['wp_version']; - - if ( function_exists('get_core_updates') ) { - $coreUpdates = get_core_updates(); - if ( is_array($coreUpdates) ) { - foreach ($coreUpdates as $coreUpdate) { - if ( isset($coreUpdate->current) ) { - $actualWpVersions[] = $coreUpdate->current; - } - } - } - } - - $actualWpVersions[] = $wpVersion; - - $actualWpPatchNumber = null; - foreach ($actualWpVersions as $version) { - if ( preg_match('/^(?P\d++\.\d++)(?:\.(?P\d++))?/', $version, $versionParts) ) { - if ( $versionParts['majorMinor'] === $update->tested ) { - $patch = isset($versionParts['patch']) ? intval($versionParts['patch']) : 0; - if ( $actualWpPatchNumber === null ) { - $actualWpPatchNumber = $patch; - } else { - $actualWpPatchNumber = max($actualWpPatchNumber, $patch); - } - } - } - } - if ( $actualWpPatchNumber === null ) { - $actualWpPatchNumber = 999; - } - - if ( $actualWpPatchNumber > 0 ) { - $update->tested .= '.' . $actualWpPatchNumber; - } - } - - /** - * Get the currently installed version of the plugin or theme. - * - * @return string|null Version number. - */ - public function getInstalledVersion() { - return $this->package->getInstalledVersion(); - } - - /** - * Get the full path of the plugin or theme directory. - * - * @return string - */ - public function getAbsoluteDirectoryPath() { - return $this->package->getAbsoluteDirectoryPath(); - } - - /** - * Trigger a PHP error, but only when $debugMode is enabled. - * - * @param string $message - * @param int $errorType - */ - public function triggerError($message, $errorType) { - if ( $this->isDebugModeEnabled() ) { - //phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_trigger_error -- Only happens in debug mode. - trigger_error(esc_html($message), $errorType); - } - } - - /** - * @return bool - */ - protected function isDebugModeEnabled() { - if ( $this->debugMode === null ) { - $this->debugMode = (bool)(constant('WP_DEBUG')); - } - return $this->debugMode; - } - - /** - * Get the full name of an update checker filter, action or DB entry. - * - * This method adds the "puc_" prefix and the "-$slug" suffix to the filter name. - * For example, "pre_inject_update" becomes "puc_pre_inject_update-plugin-slug". - * - * @param string $baseTag - * @return string - */ - public function getUniqueName($baseTag) { - $name = 'puc_' . $baseTag; - if ( $this->filterSuffix !== '' ) { - $name .= '_' . $this->filterSuffix; - } - return $name . '-' . $this->slug; - } - - /** - * Store API errors that are generated when checking for updates. - * - * @internal - * @param \WP_Error $error - * @param array|null $httpResponse - * @param string|null $url - * @param string|null $slug - */ - public function collectApiErrors($error, $httpResponse = null, $url = null, $slug = null) { - if ( isset($slug) && ($slug !== $this->slug) ) { - return; - } - - $this->lastRequestApiErrors[] = array( - 'error' => $error, - 'httpResponse' => $httpResponse, - 'url' => $url, - ); - } - - /** - * @return array - */ - public function getLastRequestApiErrors() { - return $this->lastRequestApiErrors; - } - - /* ------------------------------------------------------------------- - * PUC filters and filter utilities - * ------------------------------------------------------------------- - */ - - /** - * Register a callback for one of the update checker filters. - * - * Identical to add_filter(), except it automatically adds the "puc_" prefix - * and the "-$slug" suffix to the filter name. For example, "request_info_result" - * becomes "puc_request_info_result-your_plugin_slug". - * - * @param string $tag - * @param callable $callback - * @param int $priority - * @param int $acceptedArgs - */ - public function addFilter($tag, $callback, $priority = 10, $acceptedArgs = 1) { - add_filter($this->getUniqueName($tag), $callback, $priority, $acceptedArgs); - } - - /* ------------------------------------------------------------------- - * Inject updates - * ------------------------------------------------------------------- - */ - - /** - * Insert the latest update (if any) into the update list maintained by WP. - * - * @param \stdClass $updates Update list. - * @return \stdClass Modified update list. - */ - public function injectUpdate($updates) { - //Is there an update to insert? - $update = $this->getUpdate(); - - if ( !$this->shouldShowUpdates() ) { - $update = null; - } - - if ( !empty($update) ) { - //Let plugins filter the update info before it's passed on to WordPress. - $update = apply_filters($this->getUniqueName('pre_inject_update'), $update); - $updates = $this->addUpdateToList($updates, $update->toWpFormat()); - } else { - //Clean up any stale update info. - $updates = $this->removeUpdateFromList($updates); - //Add a placeholder item to the "no_update" list to enable auto-update support. - //If we don't do this, the option to enable automatic updates will only show up - //when an update is available. - $updates = $this->addNoUpdateItem($updates); - } - - return $updates; - } - - /** - * @param \stdClass|null $updates - * @param \stdClass|array $updateToAdd - * @return \stdClass - */ - protected function addUpdateToList($updates, $updateToAdd) { - if ( !is_object($updates) ) { - $updates = new stdClass(); - $updates->response = array(); - } - - $updates->response[$this->getUpdateListKey()] = $updateToAdd; - return $updates; - } - - /** - * @param \stdClass|null $updates - * @return \stdClass|null - */ - protected function removeUpdateFromList($updates) { - if ( isset($updates, $updates->response) ) { - unset($updates->response[$this->getUpdateListKey()]); - } - return $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 - */ - protected function addNoUpdateItem($updates) { - if ( !is_object($updates) ) { - $updates = new stdClass(); - $updates->response = array(); - $updates->no_update = array(); - } else if ( !isset($updates->no_update) ) { - $updates->no_update = array(); - } - - $updates->no_update[$this->getUpdateListKey()] = (object) $this->getNoUpdateItemFields(); - - return $updates; - } - - /** - * Subclasses should override this method to add fields that are specific to plugins or themes. - * @return array - */ - protected function getNoUpdateItemFields() { - return array( - 'new_version' => $this->getInstalledVersion(), - 'url' => '', - 'package' => '', - 'requires_php' => '', - ); - } - - /** - * Get the key that will be used when adding updates to the update list that's maintained - * by the WordPress core. The list is always an associative array, but the key is different - * for plugins and themes. - * - * @return string - */ - abstract protected function getUpdateListKey(); - - /** - * Should we show available updates? - * - * Usually the answer is "yes", but there are exceptions. For example, WordPress doesn't - * support automatic updates installation for mu-plugins, so PUC usually won't show update - * notifications in that case. See the plugin-specific subclass for details. - * - * Note: This method only applies to updates that are displayed (or not) in the WordPress - * admin. It doesn't affect APIs like requestUpdate and getUpdate. - * - * @return bool - */ - protected function shouldShowUpdates() { - return true; - } - - /* ------------------------------------------------------------------- - * JSON-based update API - * ------------------------------------------------------------------- - */ - - /** - * Retrieve plugin or theme metadata from the JSON document at $this->metadataUrl. - * - * @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 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()). - $queryArgs = array_merge( - array( - 'installed_version' => strval($this->getInstalledVersion()), - 'php' => phpversion(), - 'locale' => get_locale(), - ), - $queryArgs - ); - $queryArgs = apply_filters($this->getUniqueName($filterRoot . '_query_args'), $queryArgs); - - //Various options for the wp_remote_get() call. Plugins can filter these, too. - $options = array( - 'timeout' => wp_doing_cron() ? 10 : 3, - 'headers' => array( - 'Accept' => 'application/json', - ), - ); - $options = apply_filters($this->getUniqueName($filterRoot . '_options'), $options); - - //The metadata file should be at 'http://your-api.com/url/here/$slug/info.json' - $url = $this->metadataUrl; - if ( !empty($queryArgs) ){ - $url = add_query_arg($queryArgs, $url); - } - - $result = wp_remote_get($url, $options); - - $result = apply_filters($this->getUniqueName('request_metadata_http_result'), $result, $url, $options); - - //Try to parse the response - $status = $this->validateApiResponse($result); - $metadata = null; - if ( !is_wp_error($status) ){ - if ( (strpos($metaClass, '\\') === false) ) { - $metaClass = __NAMESPACE__ . '\\' . $metaClass; - } - $metadata = call_user_func(array($metaClass, 'fromJson'), $result['body']); - } else { - do_action('puc_api_error', $status, $result, $url, $this->slug); - $this->triggerError( - sprintf('The URL %s does not point to a valid metadata file. ', $url) - . $status->get_error_message(), - E_USER_WARNING - ); - } - - return array($metadata, $result); - } - - /** - * Check if $result is a successful update API response. - * - * @param array|WP_Error $result - * @return true|WP_Error - */ - protected function validateApiResponse($result) { - if ( is_wp_error($result) ) { /** @var WP_Error $result */ - return new WP_Error($result->get_error_code(), 'WP HTTP Error: ' . $result->get_error_message()); - } - - if ( !isset($result['response']['code']) ) { - return new WP_Error( - 'puc_no_response_code', - 'wp_remote_get() returned an unexpected result.' - ); - } - - if ( $result['response']['code'] !== 200 ) { - return new WP_Error( - 'puc_unexpected_response_code', - 'HTTP response code is ' . $result['response']['code'] . ' (expected: 200)' - ); - } - - if ( empty($result['body']) ) { - return new WP_Error('puc_empty_response', 'The metadata file appears to be empty.'); - } - - return true; - } - - /* ------------------------------------------------------------------- - * Language packs / Translation updates - * ------------------------------------------------------------------- - */ - - /** - * Filter a list of translation updates and return a new list that contains only updates - * that apply to the current site. - * - * @param array $translations - * @return array - */ - protected function filterApplicableTranslations($translations) { - $languages = array_flip(array_values(get_available_languages())); - $installedTranslations = $this->getInstalledTranslations(); - - $applicableTranslations = array(); - foreach ($translations as $translation) { - //Does it match one of the available core languages? - $isApplicable = array_key_exists($translation->language, $languages); - //Is it more recent than an already-installed translation? - if ( isset($installedTranslations[$translation->language]) ) { - $updateTimestamp = strtotime($translation->updated); - $installedTimestamp = strtotime($installedTranslations[$translation->language]['PO-Revision-Date']); - $isApplicable = $updateTimestamp > $installedTimestamp; - } - - if ( $isApplicable ) { - $applicableTranslations[] = $translation; - } - } - - return $applicableTranslations; - } - - /** - * Get a list of installed translations for this plugin or theme. - * - * @return array - */ - protected function getInstalledTranslations() { - if ( !function_exists('wp_get_installed_translations') ) { - return array(); - } - $installedTranslations = wp_get_installed_translations($this->translationType . 's'); - if ( isset($installedTranslations[$this->directoryName]) ) { - $installedTranslations = $installedTranslations[$this->directoryName]; - } else { - $installedTranslations = array(); - } - return $installedTranslations; - } - - /** - * Insert translation updates into the list maintained by WordPress. - * - * @param stdClass $updates - * @return stdClass - */ - public function injectTranslationUpdates($updates) { - $translationUpdates = $this->getTranslationUpdates(); - if ( empty($translationUpdates) ) { - return $updates; - } - - //Being defensive. - if ( !is_object($updates) ) { - $updates = new stdClass(); - } - if ( !isset($updates->translations) ) { - $updates->translations = array(); - } - - //In case there's a name collision with a plugin or theme hosted on wordpress.org, - //remove any preexisting updates that match our thing. - $updates->translations = array_values(array_filter( - $updates->translations, - array($this, 'isNotMyTranslation') - )); - - //Add our updates to the list. - foreach($translationUpdates as $update) { - $convertedUpdate = array_merge( - array( - 'type' => $this->translationType, - 'slug' => $this->directoryName, - 'autoupdate' => 0, - //AFAICT, WordPress doesn't actually use the "version" field for anything. - //But lets make sure it's there, just in case. - 'version' => isset($update->version) ? $update->version : ('1.' . strtotime($update->updated)), - ), - (array)$update - ); - - $updates->translations[] = $convertedUpdate; - } - - return $updates; - } - - /** - * Get a list of available translation updates. - * - * This method will return an empty array if there are no updates. - * Uses cached update data. - * - * @return array - */ - public function getTranslationUpdates() { - return $this->updateState->getTranslations(); - } - - /** - * Remove all cached translation updates. - * - * @see wp_clean_update_cache - */ - public function clearCachedTranslationUpdates() { - $this->updateState->setTranslations(array()); - } - - /** - * Filter callback. Keeps only translations that *don't* match this plugin or theme. - * - * @param array $translation - * @return bool - */ - protected function isNotMyTranslation($translation) { - $isMatch = isset($translation['type'], $translation['slug']) - && ($translation['type'] === $this->translationType) - && ($translation['slug'] === $this->directoryName); - - return !$isMatch; - } - - /* ------------------------------------------------------------------- - * Fix directory name when installing updates - * ------------------------------------------------------------------- - */ - - /** - * Rename the update directory to match the existing plugin/theme directory. - * - * When WordPress installs a plugin or theme update, it assumes that the ZIP file will contain - * exactly one directory, and that the directory name will be the same as the directory where - * the plugin or theme is currently installed. - * - * GitHub and other repositories provide ZIP downloads, but they often use directory names like - * "project-branch" or "project-tag-hash". We need to change the name to the actual plugin folder. - * - * This is a hook callback. Don't call it from a plugin. - * - * @access protected - * - * @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 - * @return string|WP_Error - */ - public function fixDirectoryName($source, $remoteSource, $upgrader) { - global $wp_filesystem; - /** @var \WP_Filesystem_Base $wp_filesystem */ - - //Basic sanity checks. - if ( !isset($source, $remoteSource, $upgrader, $upgrader->skin, $wp_filesystem) ) { - return $source; - } - - //If WordPress is upgrading anything other than our plugin/theme, leave the directory name unchanged. - if ( !$this->isBeingUpgraded($upgrader) ) { - return $source; - } - - //Fix the remote source structure if necessary. - //The update archive should contain a single directory that contains the rest of plugin/theme files. - //Otherwise, WordPress will try to copy the entire working directory ($source == $remoteSource). - //We can't rename $remoteSource because that would break WordPress code that cleans up temporary files - //after update. - if ( $this->isBadDirectoryStructure($remoteSource) ) { - //Create a new directory using the plugin slug. - $newDirectory = trailingslashit($remoteSource) . $this->slug . '/'; - - if ( !$wp_filesystem->is_dir($newDirectory) ) { - $wp_filesystem->mkdir($newDirectory); - - //Move all files to the newly created directory. - $sourceFiles = $wp_filesystem->dirlist($remoteSource); - if ( is_array($sourceFiles) ) { - $sourceFiles = array_keys($sourceFiles); - $allMoved = true; - foreach ($sourceFiles as $filename) { - //Skip our newly created folder. - if ( $filename === $this->slug ) { - continue; - } - - $previousSource = trailingslashit($remoteSource) . $filename; - $newSource = trailingslashit($newDirectory) . $filename; - - if ( !$wp_filesystem->move($previousSource, $newSource, true) ) { - $allMoved = false; - break; - } - } - - if ( $allMoved ) { - //Rename source. - $source = $newDirectory; - } else { - //Delete our newly created folder including all files in it. - $wp_filesystem->rmdir($newDirectory, true); - - //And return a relevant error. - return new WP_Error( - 'puc-incorrect-directory-structure', - sprintf( - 'The directory structure of the update was incorrect. All files should be inside ' . - 'a directory named %s, not at the root of the ZIP archive. Plugin Update Checker tried to fix the directory structure, but failed.', - htmlentities($this->slug) - ) - ); - } - } - } - } - - //Rename the source to match the existing directory. - $correctedSource = trailingslashit($remoteSource) . $this->directoryName . '/'; - if ( $source !== $correctedSource ) { - $upgrader->skin->feedback(sprintf( - 'Renaming %s to %s…', - '' . basename($source) . '', - '' . $this->directoryName . '' - )); - - if ( $wp_filesystem->move($source, $correctedSource, true) ) { - $upgrader->skin->feedback('Directory successfully renamed.'); - return $correctedSource; - } else { - return new WP_Error( - 'puc-rename-failed', - 'Unable to rename the update to match the existing directory.' - ); - } - } - - return $source; - } - - /** - * 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. - * @return bool - */ - abstract public function isBeingUpgraded($upgrader = null); - - /** - * Check for incorrect update directory structure. An update must contain a single directory, - * all other files should be inside that directory. - * - * @param string $remoteSource Directory path. - * @return bool - */ - protected function isBadDirectoryStructure($remoteSource) { - global $wp_filesystem; - /** @var \WP_Filesystem_Base $wp_filesystem */ - - $sourceFiles = $wp_filesystem->dirlist($remoteSource); - if ( is_array($sourceFiles) ) { - $sourceFiles = array_keys($sourceFiles); - $firstFilePath = trailingslashit($remoteSource) . $sourceFiles[0]; - return (count($sourceFiles) > 1) || (!$wp_filesystem->is_dir($firstFilePath)); - } - - //Assume it's fine. - return false; - } - - /* ------------------------------------------------------------------- - * DebugBar integration - * ------------------------------------------------------------------- - */ - - /** - * Initialize the update checker Debug Bar plugin/add-on thingy. - */ - public function maybeInitDebugBar() { - if ( - class_exists('Debug_Bar', false) - && class_exists('Debug_Bar_Panel', false) - && file_exists(dirname(__FILE__) . '/DebugBar') - ) { - $this->debugBarExtension = $this->createDebugBarExtension(); - } - } - - protected function createDebugBarExtension() { - return new DebugBar\Extension($this); - } - - /** - * Display additional configuration details in the Debug Bar panel. - * - * @param DebugBar\Panel $panel - */ - public function onDisplayConfiguration($panel) { - //Do nothing. Subclasses can use this to add additional info to the panel. - } - - } - -endif; diff --git a/vendor/yahnis-elsts/plugin-update-checker/Puc/v5p5/UpgraderStatus.php b/vendor/yahnis-elsts/plugin-update-checker/Puc/v5p5/UpgraderStatus.php deleted file mode 100644 index f06db1c..0000000 --- a/vendor/yahnis-elsts/plugin-update-checker/Puc/v5p5/UpgraderStatus.php +++ /dev/null @@ -1,200 +0,0 @@ -isBeingUpgraded('plugin', $pluginFile, $upgrader); - } - - /** - * Is there an update being installed for a specific theme? - * - * @param string $stylesheet Theme directory name. - * @param \WP_Upgrader|null $upgrader The upgrader that's performing the current update. - * @return bool - */ - public function isThemeBeingUpgraded($stylesheet, $upgrader = null) { - return $this->isBeingUpgraded('theme', $stylesheet, $upgrader); - } - - /** - * Check if a specific theme or plugin is being upgraded. - * - * @param string $type - * @param string $id - * @param \Plugin_Upgrader|\WP_Upgrader|null $upgrader - * @return bool - */ - protected function isBeingUpgraded($type, $id, $upgrader = null) { - if ( isset($upgrader) ) { - list($currentType, $currentId) = $this->getThingBeingUpgradedBy($upgrader); - if ( $currentType !== null ) { - $this->currentType = $currentType; - $this->currentId = $currentId; - } - } - return ($this->currentType === $type) && ($this->currentId === $id); - } - - /** - * Figure out which theme or plugin is being upgraded by a WP_Upgrader instance. - * - * Returns an array with two items. The first item is the type of the thing that's being - * upgraded: "plugin" or "theme". The second item is either the plugin basename or - * the theme directory name. If we can't determine what the upgrader is doing, both items - * will be NULL. - * - * Examples: - * ['plugin', 'plugin-dir-name/plugin.php'] - * ['theme', 'theme-dir-name'] - * - * @param \Plugin_Upgrader|\WP_Upgrader $upgrader - * @return array - */ - private function getThingBeingUpgradedBy($upgrader) { - if ( !isset($upgrader, $upgrader->skin) ) { - return array(null, null); - } - - //Figure out which plugin or theme is being upgraded. - $pluginFile = null; - $themeDirectoryName = null; - - $skin = $upgrader->skin; - if ( isset($skin->theme_info) && ($skin->theme_info instanceof \WP_Theme) ) { - $themeDirectoryName = $skin->theme_info->get_stylesheet(); - } 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 ) { - if ( isset($skin->theme) && is_string($skin->theme) && ($skin->theme !== '') ) { - $themeDirectoryName = $skin->theme; - } - } elseif ( isset($skin->plugin_info) && is_array($skin->plugin_info) ) { - //This case is tricky because Bulk_Plugin_Upgrader_Skin (etc) doesn't actually store the plugin - //filename anywhere. Instead, it has the plugin headers in $plugin_info. So the best we can - //do is compare those headers to the headers of installed plugins. - $pluginFile = $this->identifyPluginByHeaders($skin->plugin_info); - } - - if ( $pluginFile !== null ) { - return array('plugin', $pluginFile); - } elseif ( $themeDirectoryName !== null ) { - return array('theme', $themeDirectoryName); - } - return array(null, null); - } - - /** - * Identify an installed plugin based on its headers. - * - * @param array $searchHeaders The plugin file header to look for. - * @return string|null Plugin basename ("foo/bar.php"), or NULL if we can't identify the plugin. - */ - private function identifyPluginByHeaders($searchHeaders) { - if ( !function_exists('get_plugins') ){ - require_once( ABSPATH . '/wp-admin/includes/plugin.php' ); - } - - $installedPlugins = get_plugins(); - $matches = array(); - foreach($installedPlugins as $pluginBasename => $headers) { - $diff1 = array_diff_assoc($headers, $searchHeaders); - $diff2 = array_diff_assoc($searchHeaders, $headers); - if ( empty($diff1) && empty($diff2) ) { - $matches[] = $pluginBasename; - } - } - - //It's possible (though very unlikely) that there could be two plugins with identical - //headers. In that case, we can't unambiguously identify the plugin that's being upgraded. - if ( count($matches) !== 1 ) { - return null; - } - - return reset($matches); - } - - /** - * @access private - * - * @param mixed $input - * @param array $hookExtra - * @return mixed Returns $input unaltered. - */ - public function setUpgradedThing($input, $hookExtra) { - if ( !empty($hookExtra['plugin']) && is_string($hookExtra['plugin']) ) { - $this->currentId = $hookExtra['plugin']; - $this->currentType = 'plugin'; - } elseif ( !empty($hookExtra['theme']) && is_string($hookExtra['theme']) ) { - $this->currentId = $hookExtra['theme']; - $this->currentType = 'theme'; - } else { - $this->currentType = null; - $this->currentId = null; - } - return $input; - } - - /** - * @access private - * - * @param array $options - * @return array - */ - public function setUpgradedPluginFromOptions($options) { - if ( isset($options['hook_extra']['plugin']) && is_string($options['hook_extra']['plugin']) ) { - $this->currentType = 'plugin'; - $this->currentId = $options['hook_extra']['plugin']; - } else { - $this->currentType = null; - $this->currentId = null; - } - return $options; - } - - /** - * @access private - * - * @param mixed $input - * @return mixed Returns $input unaltered. - */ - public function clearUpgradedThing($input = null) { - $this->currentId = null; - $this->currentType = null; - return $input; - } - } - -endif; diff --git a/vendor/yahnis-elsts/plugin-update-checker/Puc/v5p5/Utils.php b/vendor/yahnis-elsts/plugin-update-checker/Puc/v5p5/Utils.php deleted file mode 100644 index 8aecb75..0000000 --- a/vendor/yahnis-elsts/plugin-update-checker/Puc/v5p5/Utils.php +++ /dev/null @@ -1,70 +0,0 @@ -$node) ) { - $currentValue = $currentValue->$node; - } else { - return $default; - } - } - - return $currentValue; - } - - /** - * Get the first array element that is not empty. - * - * @param array $values - * @param mixed|null $default Returns this value if there are no non-empty elements. - * @return mixed|null - */ - public static function findNotEmpty($values, $default = null) { - if ( empty($values) ) { - return $default; - } - - foreach ($values as $value) { - if ( !empty($value) ) { - return $value; - } - } - - return $default; - } - - /** - * Check if the input string starts with the specified prefix. - * - * @param string $input - * @param string $prefix - * @return bool - */ - public static function startsWith($input, $prefix) { - $length = strlen($prefix); - return (substr($input, 0, $length) === $prefix); - } - } - -endif; diff --git a/vendor/yahnis-elsts/plugin-update-checker/Puc/v5p5/Vcs/Api.php b/vendor/yahnis-elsts/plugin-update-checker/Puc/v5p5/Vcs/Api.php deleted file mode 100644 index c7f44ce..0000000 --- a/vendor/yahnis-elsts/plugin-update-checker/Puc/v5p5/Vcs/Api.php +++ /dev/null @@ -1,379 +0,0 @@ -repositoryUrl = $repositoryUrl; - $this->setAuthentication($credentials); - } - - /** - * @return string - */ - public function getRepositoryUrl() { - return $this->repositoryUrl; - } - - /** - * Figure out which reference (i.e. tag or branch) contains the latest version. - * - * @param string $configBranch Start looking in this branch. - * @return null|Reference - */ - public function chooseReference($configBranch) { - $strategies = $this->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 - * according to the plugin readme standard. - * - * @param string $ref Tag or branch name. - * @return array Parsed readme. - */ - public function getRemoteReadme($ref = 'master') { - $fileContents = $this->getRemoteFile($this->getLocalReadmeName(), $ref); - if ( empty($fileContents) ) { - return array(); - } - - $parser = new PucReadmeParser(); - return $parser->parse_readme_contents($fileContents); - } - - /** - * Get the case-sensitive name of the local readme.txt file. - * - * In most cases it should just be called "readme.txt", but some plugins call it "README.txt", - * "README.TXT", or even "Readme.txt". Most VCS are case-sensitive so we need to know the correct - * capitalization. - * - * Defaults to "readme.txt" (all lowercase). - * - * @return string - */ - public function getLocalReadmeName() { - static $fileName = null; - if ( $fileName !== null ) { - return $fileName; - } - - $fileName = 'readme.txt'; - if ( isset($this->localDirectory) ) { - $files = scandir($this->localDirectory); - if ( !empty($files) ) { - foreach ($files as $possibleFileName) { - if ( strcasecmp($possibleFileName, 'readme.txt') === 0 ) { - $fileName = $possibleFileName; - break; - } - } - } - } - return $fileName; - } - - /** - * Get a branch. - * - * @param string $branchName - * @return Reference|null - */ - abstract public function getBranch($branchName); - - /** - * Get a specific tag. - * - * @param string $tagName - * @return Reference|null - */ - abstract public function getTag($tagName); - - /** - * Get the tag that looks like the highest version number. - * (Implementations should skip pre-release versions if possible.) - * - * @return Reference|null - */ - abstract public function getLatestTag(); - - /** - * Check if a tag name string looks like a version number. - * - * @param string $name - * @return bool - */ - protected function looksLikeVersion($name) { - //Tag names may be prefixed with "v", e.g. "v1.2.3". - $name = ltrim($name, 'v'); - - //The version string must start with a number. - if ( !is_numeric(substr($name, 0, 1)) ) { - return false; - } - - //The goal is to accept any SemVer-compatible or "PHP-standardized" version number. - return (preg_match('@^(\d{1,5}?)(\.\d{1,10}?){0,4}?($|[abrdp+_\-]|\s)@i', $name) === 1); - } - - /** - * Check if a tag appears to be named like a version number. - * - * @param \stdClass $tag - * @return bool - */ - protected function isVersionTag($tag) { - $property = $this->tagNameProperty; - return isset($tag->$property) && $this->looksLikeVersion($tag->$property); - } - - /** - * 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. - */ - protected function sortTagsByVersion($tags) { - //Keep only those tags that look like version numbers. - $versionTags = array_filter($tags, array($this, 'isVersionTag')); - //Sort them in descending order. - usort($versionTags, array($this, 'compareTagNames')); - - return $versionTags; - } - - /** - * Compare two tags as if they were version number. - * - * @param \stdClass $tag1 Tag object. - * @param \stdClass $tag2 Another tag object. - * @return int - */ - protected function compareTagNames($tag1, $tag2) { - $property = $this->tagNameProperty; - if ( !isset($tag1->$property) ) { - return 1; - } - if ( !isset($tag2->$property) ) { - return -1; - } - return -version_compare(ltrim($tag1->$property, 'v'), ltrim($tag2->$property, 'v')); - } - - /** - * Get the contents of a file from a specific branch or tag. - * - * @param string $path File name. - * @param string $ref - * @return null|string Either the contents of the file, or null if the file doesn't exist or there's an error. - */ - abstract public function getRemoteFile($path, $ref = 'master'); - - /** - * Get the timestamp of the latest commit that changed the specified branch or tag. - * - * @param string $ref Reference name (e.g. branch or tag). - * @return string|null - */ - abstract public function getLatestCommitTime($ref); - - /** - * Get the contents of the changelog file from the repository. - * - * @param string $ref - * @param string $localDirectory Full path to the local plugin or theme directory. - * @return null|string The HTML contents of the changelog. - */ - public function getRemoteChangelog($ref, $localDirectory) { - $filename = $this->findChangelogName($localDirectory); - if ( empty($filename) ) { - return null; - } - - $changelog = $this->getRemoteFile($filename, $ref); - if ( $changelog === null ) { - return null; - } - - return Parsedown::instance()->text($changelog); - } - - /** - * Guess the name of the changelog file. - * - * @param string $directory - * @return string|null - */ - protected function findChangelogName($directory = null) { - if ( !isset($directory) ) { - $directory = $this->localDirectory; - } - if ( empty($directory) || !is_dir($directory) || ($directory === '.') ) { - return null; - } - - $possibleNames = array('CHANGES.md', 'CHANGELOG.md', 'changes.md', 'changelog.md'); - $files = scandir($directory); - $foundNames = array_intersect($possibleNames, $files); - - if ( !empty($foundNames) ) { - return reset($foundNames); - } - return null; - } - - /** - * Set authentication credentials. - * - * @param $credentials - */ - public function setAuthentication($credentials) { - $this->credentials = $credentials; - } - - public function isAuthenticationEnabled() { - return !empty($this->credentials); - } - - /** - * @param string $url - * @return string - */ - public function signDownloadUrl($url) { - return $url; - } - - /** - * @param string $filterName - */ - public function setHttpFilterName($filterName) { - $this->httpFilterName = $filterName; - } - - /** - * @param string $filterName - */ - public function setStrategyFilterName($filterName) { - $this->strategyFilterName = $filterName; - } - - /** - * @param string $directory - */ - public function setLocalDirectory($directory) { - if ( empty($directory) || !is_dir($directory) || ($directory === '.') ) { - $this->localDirectory = null; - } else { - $this->localDirectory = $directory; - } - } - - /** - * @param string $slug - */ - public function setSlug($slug) { - $this->slug = $slug; - } - } - -endif; diff --git a/vendor/yahnis-elsts/plugin-update-checker/Puc/v5p5/Vcs/BaseChecker.php b/vendor/yahnis-elsts/plugin-update-checker/Puc/v5p5/Vcs/BaseChecker.php deleted file mode 100644 index d1cdc7b..0000000 --- a/vendor/yahnis-elsts/plugin-update-checker/Puc/v5p5/Vcs/BaseChecker.php +++ /dev/null @@ -1,29 +0,0 @@ -[^/]+?)/(?P[^/#?&]+?)/?$@', $path, $matches) ) { - $this->username = $matches['username']; - $this->repository = $matches['repository']; - } else { - throw new \InvalidArgumentException('Invalid BitBucket repository URL: "' . $repositoryUrl . '"'); - } - - parent::__construct($repositoryUrl, $credentials); - } - - protected function getUpdateDetectionStrategies($configBranch) { - $strategies = array( - self::STRATEGY_STABLE_TAG => function () use ($configBranch) { - return $this->getStableTag($configBranch); - }, - ); - - if ( ($configBranch === 'master' || $configBranch === 'main') ) { - $strategies[self::STRATEGY_LATEST_TAG] = array($this, 'getLatestTag'); - } - - $strategies[self::STRATEGY_BRANCH] = function () use ($configBranch) { - return $this->getBranch($configBranch); - }; - return $strategies; - } - - public function getBranch($branchName) { - $branch = $this->api('/refs/branches/' . $branchName); - if ( is_wp_error($branch) || empty($branch) ) { - return null; - } - - //The "/src/{stuff}/{path}" endpoint doesn't seem to handle branch names that contain slashes. - //If we don't encode the slash, we get a 404. If we encode it as "%2F", we get a 401. - //To avoid issues, if the branch name is not URL-safe, let's use the commit hash instead. - $ref = $branch->name; - if ((urlencode($ref) !== $ref) && isset($branch->target->hash)) { - $ref = $branch->target->hash; - } - - return new Reference(array( - 'name' => $ref, - 'updated' => $branch->target->date, - 'downloadUrl' => $this->getDownloadUrl($branch->name), - )); - } - - /** - * Get a specific tag. - * - * @param string $tagName - * @return Reference|null - */ - public function getTag($tagName) { - $tag = $this->api('/refs/tags/' . $tagName); - if ( is_wp_error($tag) || empty($tag) ) { - return null; - } - - return new Reference(array( - 'name' => $tag->name, - 'version' => ltrim($tag->name, 'v'), - 'updated' => $tag->target->date, - 'downloadUrl' => $this->getDownloadUrl($tag->name), - )); - } - - /** - * Get the tag that looks like the highest version number. - * - * @return Reference|null - */ - public function getLatestTag() { - $tags = $this->api('/refs/tags?sort=-target.date'); - if ( !isset($tags, $tags->values) || !is_array($tags->values) ) { - return null; - } - - //Filter and sort the list of tags. - $versionTags = $this->sortTagsByVersion($tags->values); - - //Return the first result. - if ( !empty($versionTags) ) { - $tag = $versionTags[0]; - return new Reference(array( - 'name' => $tag->name, - 'version' => ltrim($tag->name, 'v'), - 'updated' => $tag->target->date, - 'downloadUrl' => $this->getDownloadUrl($tag->name), - )); - } - return null; - } - - /** - * Get the tag/ref specified by the "Stable tag" header in the readme.txt of a given branch. - * - * @param string $branch - * @return null|Reference - */ - protected function getStableTag($branch) { - $remoteReadme = $this->getRemoteReadme($branch); - if ( !empty($remoteReadme['stable_tag']) ) { - $tag = $remoteReadme['stable_tag']; - - //You can explicitly opt out of using tags by setting "Stable tag" to - //"trunk" or the name of the current branch. - if ( ($tag === $branch) || ($tag === 'trunk') ) { - return $this->getBranch($branch); - } - - return $this->getTag($tag); - } - - return null; - } - - /** - * @param string $ref - * @return string - */ - protected function getDownloadUrl($ref) { - return sprintf( - 'https://bitbucket.org/%s/%s/get/%s.zip', - $this->username, - $this->repository, - $ref - ); - } - - /** - * Get the contents of a file from a specific branch or tag. - * - * @param string $path File name. - * @param string $ref - * @return null|string Either the contents of the file, or null if the file doesn't exist or there's an error. - */ - public function getRemoteFile($path, $ref = 'master') { - $response = $this->api('src/' . $ref . '/' . ltrim($path)); - if ( is_wp_error($response) || !is_string($response) ) { - return null; - } - return $response; - } - - /** - * Get the timestamp of the latest commit that changed the specified branch or tag. - * - * @param string $ref Reference name (e.g. branch or tag). - * @return string|null - */ - public function getLatestCommitTime($ref) { - $response = $this->api('commits/' . $ref); - if ( isset($response->values, $response->values[0], $response->values[0]->date) ) { - return $response->values[0]->date; - } - return null; - } - - /** - * Perform a BitBucket API 2.0 request. - * - * @param string $url - * @param string $version - * @return mixed|\WP_Error - */ - public function api($url, $version = '2.0') { - $url = ltrim($url, '/'); - $isSrcResource = Utils::startsWith($url, 'src/'); - - $url = implode('/', array( - 'https://api.bitbucket.org', - $version, - 'repositories', - $this->username, - $this->repository, - $url - )); - $baseUrl = $url; - - if ( $this->oauth ) { - $url = $this->oauth->sign($url,'GET'); - } - - $options = array('timeout' => wp_doing_cron() ? 10 : 3); - if ( !empty($this->httpFilterName) ) { - $options = apply_filters($this->httpFilterName, $options); - } - $response = wp_remote_get($url, $options); - if ( is_wp_error($response) ) { - do_action('puc_api_error', $response, null, $url, $this->slug); - return $response; - } - - $code = wp_remote_retrieve_response_code($response); - $body = wp_remote_retrieve_body($response); - if ( $code === 200 ) { - if ( $isSrcResource ) { - //Most responses are JSON-encoded, but src resources just - //return raw file contents. - $document = $body; - } else { - $document = json_decode($body); - } - return $document; - } - - $error = new \WP_Error( - 'puc-bitbucket-http-error', - sprintf('BitBucket API error. Base URL: "%s", HTTP status code: %d.', $baseUrl, $code) - ); - do_action('puc_api_error', $error, $response, $url, $this->slug); - - return $error; - } - - /** - * @param array $credentials - */ - public function setAuthentication($credentials) { - parent::setAuthentication($credentials); - - if ( !empty($credentials) && !empty($credentials['consumer_key']) ) { - $this->oauth = new OAuthSignature( - $credentials['consumer_key'], - $credentials['consumer_secret'] - ); - } else { - $this->oauth = null; - } - } - - 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, - //authentication could fail due to a stale timestamp. - if ( $this->oauth ) { - $url = $this->oauth->sign($url); - } - return $url; - } - } - -endif; diff --git a/vendor/yahnis-elsts/plugin-update-checker/Puc/v5p5/Vcs/GitHubApi.php b/vendor/yahnis-elsts/plugin-update-checker/Puc/v5p5/Vcs/GitHubApi.php deleted file mode 100644 index 0eb0e56..0000000 --- a/vendor/yahnis-elsts/plugin-update-checker/Puc/v5p5/Vcs/GitHubApi.php +++ /dev/null @@ -1,467 +0,0 @@ -[^/]+?)/(?P[^/#?&]+?)/?$@', $path, $matches) ) { - $this->userName = $matches['username']; - $this->repositoryName = $matches['repository']; - } else { - throw new \InvalidArgumentException('Invalid GitHub repository URL: "' . $repositoryUrl . '"'); - } - - parent::__construct($repositoryUrl, $accessToken); - } - - /** - * Get the latest release from GitHub. - * - * @return Reference|null - */ - public function getLatestRelease() { - //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; - } - } - - foreach ($foundReleases as $release) { - //Always skip drafts. - if ( isset($release->draft) && !empty($release->draft) ) { - continue; - } - - //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 ) { - //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 { - $matchingAssets = array(); - } - - 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) ) { - $reference->changelog = Parsedown::instance()->text($release->body); - } - - return $reference; - } - - return null; - } - - /** - * Get the tag that looks like the highest version number. - * - * @return Reference|null - */ - public function getLatestTag() { - $tags = $this->api('/repos/:user/:repo/tags'); - - if ( is_wp_error($tags) || !is_array($tags) ) { - return null; - } - - $versionTags = $this->sortTagsByVersion($tags); - if ( empty($versionTags) ) { - return null; - } - - $tag = $versionTags[0]; - return new Reference(array( - 'name' => $tag->name, - 'version' => ltrim($tag->name, 'v'), - 'downloadUrl' => $tag->zipball_url, - 'apiResponse' => $tag, - )); - } - - /** - * Get a branch by name. - * - * @param string $branchName - * @return null|Reference - */ - public function getBranch($branchName) { - $branch = $this->api('/repos/:user/:repo/branches/' . $branchName); - if ( is_wp_error($branch) || empty($branch) ) { - return null; - } - - $reference = new Reference(array( - 'name' => $branch->name, - 'downloadUrl' => $this->buildArchiveDownloadUrl($branch->name), - 'apiResponse' => $branch, - )); - - if ( isset($branch->commit, $branch->commit->commit, $branch->commit->commit->author->date) ) { - $reference->updated = $branch->commit->commit->author->date; - } - - return $reference; - } - - /** - * Get the latest commit that changed the specified file. - * - * @param string $filename - * @param string $ref Reference name (e.g. branch or tag). - * @return \StdClass|null - */ - public function getLatestCommit($filename, $ref = 'master') { - $commits = $this->api( - '/repos/:user/:repo/commits', - array( - 'path' => $filename, - 'sha' => $ref, - ) - ); - if ( !is_wp_error($commits) && isset($commits[0]) ) { - return $commits[0]; - } - return null; - } - - /** - * Get the timestamp of the latest commit that changed the specified branch or tag. - * - * @param string $ref Reference name (e.g. branch or tag). - * @return string|null - */ - public function getLatestCommitTime($ref) { - $commits = $this->api('/repos/:user/:repo/commits', array('sha' => $ref)); - if ( !is_wp_error($commits) && isset($commits[0]) ) { - return $commits[0]->commit->author->date; - } - return null; - } - - /** - * Perform a GitHub API request. - * - * @param string $url - * @param array $queryParams - * @return mixed|\WP_Error - */ - protected function api($url, $queryParams = array()) { - $baseUrl = $url; - $url = $this->buildApiUrl($url, $queryParams); - - $options = array('timeout' => wp_doing_cron() ? 10 : 3); - if ( $this->isAuthenticationEnabled() ) { - $options['headers'] = array('Authorization' => $this->getAuthorizationHeader()); - } - - if ( !empty($this->httpFilterName) ) { - $options = apply_filters($this->httpFilterName, $options); - } - $response = wp_remote_get($url, $options); - if ( is_wp_error($response) ) { - do_action('puc_api_error', $response, null, $url, $this->slug); - return $response; - } - - $code = wp_remote_retrieve_response_code($response); - $body = wp_remote_retrieve_body($response); - if ( $code === 200 ) { - $document = json_decode($body); - return $document; - } - - $error = new \WP_Error( - 'puc-github-http-error', - sprintf('GitHub API error. Base URL: "%s", HTTP status code: %d.', $baseUrl, $code) - ); - do_action('puc_api_error', $error, $response, $url, $this->slug); - - return $error; - } - - /** - * Build a fully qualified URL for an API request. - * - * @param string $url - * @param array $queryParams - * @return string - */ - protected function buildApiUrl($url, $queryParams) { - $variables = array( - 'user' => $this->userName, - 'repo' => $this->repositoryName, - ); - foreach ($variables as $name => $value) { - $url = str_replace('/:' . $name, '/' . urlencode($value), $url); - } - $url = 'https://api.github.com' . $url; - - if ( !empty($queryParams) ) { - $url = add_query_arg($queryParams, $url); - } - - return $url; - } - - /** - * Get the contents of a file from a specific branch or tag. - * - * @param string $path File name. - * @param string $ref - * @return null|string Either the contents of the file, or null if the file doesn't exist or there's an error. - */ - public function getRemoteFile($path, $ref = 'master') { - $apiUrl = '/repos/:user/:repo/contents/' . $path; - $response = $this->api($apiUrl, array('ref' => $ref)); - - if ( is_wp_error($response) || !isset($response->content) || ($response->encoding !== 'base64') ) { - return null; - } - return base64_decode($response->content); - } - - /** - * Generate a URL to download a ZIP archive of the specified branch/tag/etc. - * - * @param string $ref - * @return string - */ - public function buildArchiveDownloadUrl($ref = 'master') { - $url = sprintf( - 'https://api.github.com/repos/%1$s/%2$s/zipball/%3$s', - urlencode($this->userName), - urlencode($this->repositoryName), - urlencode($ref) - ); - return $url; - } - - /** - * Get a specific tag. - * - * @param string $tagName - * @return void - */ - 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.'); - } - - public function setAuthentication($credentials) { - parent::setAuthentication($credentials); - $this->accessToken = is_string($credentials) ? $credentials : null; - - //Optimization: Instead of filtering all HTTP requests, let's do it only when - //WordPress is about to download an update. - add_filter('upgrader_pre_download', array($this, 'addHttpRequestFilter'), 10, 1); //WP 3.7+ - } - - protected function getUpdateDetectionStrategies($configBranch) { - $strategies = array(); - - if ( $configBranch === 'master' || $configBranch === 'main') { - //Use the latest release. - $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. - $strategies[self::STRATEGY_BRANCH] = function () use ($configBranch) { - return $this->getBranch($configBranch); - }; - - return $strategies; - } - - /** - * Get the unchanging part of a release asset URL. Used to identify download attempts. - * - * @return string - */ - protected function getAssetApiBaseUrl() { - return sprintf( - '//api.github.com/repos/%1$s/%2$s/releases/assets/', - $this->userName, - $this->repositoryName - ); - } - - protected function getFilterableAssetName($releaseAsset) { - if ( isset($releaseAsset->name) ) { - return $releaseAsset->name; - } - return null; - } - - /** - * @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; - } - return $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 - * - * @internal - * @param array $requestArgs - * @param string $url - * @return array - */ - public function setUpdateDownloadHeaders($requestArgs, $url = '') { - //Is WordPress trying to download one of our release assets? - 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. - $repoApiBaseUrl = $this->buildApiUrl('/repos/:user/:repo/', array()); - if ( $this->isAuthenticationEnabled() && (strpos($url, $repoApiBaseUrl)) === 0 ) { - $requestArgs['headers']['Authorization'] = $this->getAuthorizationHeader(); - } - return $requestArgs; - } - - /** - * When following a redirect, the Requests library will automatically forward - * the authorization header to other hosts. We don't want that because it breaks - * AWS downloads and can leak authorization information. - * - * @param string $location - * @param array $headers - * @internal - */ - public function removeAuthHeaderFromRedirects(&$location, &$headers) { - $repoApiBaseUrl = $this->buildApiUrl('/repos/:user/:repo/', array()); - if ( strpos($location, $repoApiBaseUrl) === 0 ) { - return; //This request is going to GitHub, so it's fine. - } - //Remove the header. - if ( isset($headers['Authorization']) ) { - unset($headers['Authorization']); - } - } - - /** - * Generate the value of the "Authorization" header. - * - * @return string - */ - protected function getAuthorizationHeader() { - return 'Basic ' . base64_encode($this->userName . ':' . $this->accessToken); - } - } - -endif; diff --git a/vendor/yahnis-elsts/plugin-update-checker/Puc/v5p5/Vcs/GitLabApi.php b/vendor/yahnis-elsts/plugin-update-checker/Puc/v5p5/Vcs/GitLabApi.php deleted file mode 100644 index 4d9350a..0000000 --- a/vendor/yahnis-elsts/plugin-update-checker/Puc/v5p5/Vcs/GitLabApi.php +++ /dev/null @@ -1,414 +0,0 @@ -repositoryHost = wp_parse_url($repositoryUrl, PHP_URL_HOST) . $port; - - if ( $this->repositoryHost !== 'gitlab.com' ) { - $this->repositoryProtocol = wp_parse_url($repositoryUrl, PHP_URL_SCHEME); - } - - //Find the repository information - $path = wp_parse_url($repositoryUrl, PHP_URL_PATH); - if ( preg_match('@^/?(?P[^/]+?)/(?P[^/#?&]+?)/?$@', $path, $matches) ) { - $this->userName = $matches['username']; - $this->repositoryName = $matches['repository']; - } elseif ( ($this->repositoryHost === 'gitlab.com') ) { - //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 . '"'); - } - $lastPart = array_pop($parts); - $this->userName = implode('/', $parts); - $this->repositoryName = $lastPart; - } else { - //There could be subgroups in the URL: gitlab.domain.com/group/subgroup/subgroup2/repository - if ( $subgroup !== null ) { - $path = str_replace(trailingslashit($subgroup), '', $path); - } - - //This is not a traditional url, it could be gitlab is in a deeper subdirectory. - //Get the path segments. - $segments = explode('/', untrailingslashit(ltrim($path, '/'))); - - //We need at least /user-name/repository-name/ - if ( count($segments) < 2 ) { - throw new \InvalidArgumentException('Invalid GitLab repository URL: "' . $repositoryUrl . '"'); - } - - //Get the username and repository name. - $usernameRepo = array_splice($segments, -2, 2); - $this->userName = $usernameRepo[0]; - $this->repositoryName = $usernameRepo[1]; - - //Append the remaining segments to the host if there are segments left. - if ( count($segments) > 0 ) { - $this->repositoryHost = trailingslashit($this->repositoryHost) . implode('/', $segments); - } - - //Add subgroups to username. - if ( $subgroup !== null ) { - $this->userName = $usernameRepo[0] . '/' . untrailingslashit($subgroup); - } - } - - parent::__construct($repositoryUrl, $accessToken); - } - - /** - * Get the latest release from GitLab. - * - * @return Reference|null - */ - public function getLatestRelease() { - $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 ( - //Skip invalid/unsupported releases. - !is_object($release) - || !isset($release->tag_name) - //Skip upcoming releases. - || ( - !empty($release->upcoming_release) - && $this->shouldSkipPreReleases() - ) - ) { - continue; - } - - $versionNumber = ltrim($release->tag_name, 'v'); //Remove the "v" prefix from "v1.2.3". - - //Apply custom filters. - if ( !$this->matchesCustomReleaseFilter($versionNumber, $release) ) { - continue; - } - - $downloadUrl = $this->findReleaseDownloadUrl($release); - if ( empty($downloadUrl) ) { - //The latest release doesn't have valid download URL. - return null; - } - - if ( !empty($this->accessToken) ) { - $downloadUrl = add_query_arg('private_token', $this->accessToken, $downloadUrl); - } - - 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 ( $this->releaseAssetPreference === Api::REQUIRE_RELEASE_ASSETS ) { - //Falling back to source archives is not allowed, so give up. - return null; - } - } - - //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; - } - } - - return null; - } - - /** - * Get the tag that looks like the highest version number. - * - * @return Reference|null - */ - public function getLatestTag() { - $tags = $this->api('/:id/repository/tags'); - if ( is_wp_error($tags) || empty($tags) || !is_array($tags) ) { - return null; - } - - $versionTags = $this->sortTagsByVersion($tags); - if ( empty($versionTags) ) { - return null; - } - - $tag = $versionTags[0]; - return new Reference(array( - 'name' => $tag->name, - 'version' => ltrim($tag->name, 'v'), - 'downloadUrl' => $this->buildArchiveDownloadUrl($tag->name), - 'apiResponse' => $tag, - )); - } - - /** - * Get a branch by name. - * - * @param string $branchName - * @return null|Reference - */ - public function getBranch($branchName) { - $branch = $this->api('/:id/repository/branches/' . $branchName); - if ( is_wp_error($branch) || empty($branch) ) { - return null; - } - - $reference = new Reference(array( - 'name' => $branch->name, - 'downloadUrl' => $this->buildArchiveDownloadUrl($branch->name), - 'apiResponse' => $branch, - )); - - if ( isset($branch->commit, $branch->commit->committed_date) ) { - $reference->updated = $branch->commit->committed_date; - } - - return $reference; - } - - /** - * Get the timestamp of the latest commit that changed the specified branch or tag. - * - * @param string $ref Reference name (e.g. branch or tag). - * @return string|null - */ - public function getLatestCommitTime($ref) { - $commits = $this->api('/:id/repository/commits/', array('ref_name' => $ref)); - if ( is_wp_error($commits) || !is_array($commits) || !isset($commits[0]) ) { - return null; - } - - return $commits[0]->committed_date; - } - - /** - * Perform a GitLab API request. - * - * @param string $url - * @param array $queryParams - * @return mixed|\WP_Error - */ - protected function api($url, $queryParams = array()) { - $baseUrl = $url; - $url = $this->buildApiUrl($url, $queryParams); - - $options = array('timeout' => wp_doing_cron() ? 10 : 3); - if ( !empty($this->httpFilterName) ) { - $options = apply_filters($this->httpFilterName, $options); - } - - $response = wp_remote_get($url, $options); - if ( is_wp_error($response) ) { - do_action('puc_api_error', $response, null, $url, $this->slug); - return $response; - } - - $code = wp_remote_retrieve_response_code($response); - $body = wp_remote_retrieve_body($response); - if ( $code === 200 ) { - return json_decode($body); - } - - $error = new \WP_Error( - 'puc-gitlab-http-error', - sprintf('GitLab API error. URL: "%s", HTTP status code: %d.', $baseUrl, $code) - ); - do_action('puc_api_error', $error, $response, $url, $this->slug); - - return $error; - } - - /** - * Build a fully qualified URL for an API request. - * - * @param string $url - * @param array $queryParams - * @return string - */ - protected function buildApiUrl($url, $queryParams) { - $variables = array( - 'user' => $this->userName, - 'repo' => $this->repositoryName, - 'id' => $this->userName . '/' . $this->repositoryName, - ); - - foreach ($variables as $name => $value) { - $url = str_replace("/:{$name}", '/' . urlencode($value), $url); - } - - $url = substr($url, 1); - $url = sprintf('%1$s://%2$s/api/v4/projects/%3$s', $this->repositoryProtocol, $this->repositoryHost, $url); - - if ( !empty($this->accessToken) ) { - $queryParams['private_token'] = $this->accessToken; - } - - if ( !empty($queryParams) ) { - $url = add_query_arg($queryParams, $url); - } - - return $url; - } - - /** - * Get the contents of a file from a specific branch or tag. - * - * @param string $path File name. - * @param string $ref - * @return null|string Either the contents of the file, or null if the file doesn't exist or there's an error. - */ - public function getRemoteFile($path, $ref = 'master') { - $response = $this->api('/:id/repository/files/' . $path, array('ref' => $ref)); - if ( is_wp_error($response) || !isset($response->content) || $response->encoding !== 'base64' ) { - return null; - } - - return base64_decode($response->content); - } - - /** - * Generate a URL to download a ZIP archive of the specified branch/tag/etc. - * - * @param string $ref - * @return string - */ - public function buildArchiveDownloadUrl($ref = 'master') { - $url = sprintf( - '%1$s://%2$s/api/v4/projects/%3$s/repository/archive.zip', - $this->repositoryProtocol, - $this->repositoryHost, - urlencode($this->userName . '/' . $this->repositoryName) - ); - $url = add_query_arg('sha', urlencode($ref), $url); - - if ( !empty($this->accessToken) ) { - $url = add_query_arg('private_token', $this->accessToken, $url); - } - - return $url; - } - - /** - * Get a specific tag. - * - * @param string $tagName - * @return void - */ - public function getTag($tagName) { - throw new \LogicException('The ' . __METHOD__ . ' method is not implemented and should not be used.'); - } - - 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'); - } - - $strategies[self::STRATEGY_BRANCH] = function () use ($configBranch) { - return $this->getBranch($configBranch); - }; - - return $strategies; - } - - public function setAuthentication($credentials) { - parent::setAuthentication($credentials); - $this->accessToken = is_string($credentials) ? $credentials : null; - } - - /** - * 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->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/v5p5/Vcs/PluginUpdateChecker.php b/vendor/yahnis-elsts/plugin-update-checker/Puc/v5p5/Vcs/PluginUpdateChecker.php deleted file mode 100644 index 20a6f4a..0000000 --- a/vendor/yahnis-elsts/plugin-update-checker/Puc/v5p5/Vcs/PluginUpdateChecker.php +++ /dev/null @@ -1,275 +0,0 @@ -api = $api; - - 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); - } - - public function requestInfo($unusedParameter = null) { - //We have to make several remote API requests to gather all the necessary info - //which can take a while on slow networks. - if ( function_exists('set_time_limit') ) { - @set_time_limit(60); - } - - $api = $this->api; - $api->setLocalDirectory($this->package->getAbsoluteDirectoryPath()); - - $info = new Plugin\PluginInfo(); - $info->filename = $this->pluginFile; - $info->slug = $this->slug; - - $this->setInfoFromHeader($this->package->getPluginHeader(), $info); - $this->setIconsFromLocalAssets($info); - $this->setBannersFromLocalAssets($info); - - //Pick a branch or tag. - $updateSource = $api->chooseReference($this->branch); - if ( $updateSource ) { - $ref = $updateSource->name; - $info->version = $updateSource->version; - $info->last_updated = $updateSource->updated; - $info->download_url = $updateSource->downloadUrl; - - if ( !empty($updateSource->changelog) ) { - $info->sections['changelog'] = $updateSource->changelog; - } - if ( isset($updateSource->downloadCount) ) { - $info->downloaded = $updateSource->downloadCount; - } - } else { - //There's probably a network problem or an authentication error. - do_action( - 'puc_api_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 ' - . 'to the repository or it\'s configured incorrectly.' - ), - null, null, $this->slug - ); - return null; - } - - //Get headers from the main plugin file 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. - $mainPluginFile = basename($this->pluginFile); - $remotePlugin = $api->getRemoteFile($mainPluginFile, $ref); - if ( !empty($remotePlugin) ) { - $remoteHeader = $this->package->getFileHeader($remotePlugin); - $this->setInfoFromHeader($remoteHeader, $info); - } - - //Sanity check: Reject updates that don't have a version number. - //This can happen when we're using a branch, and we either fail to retrieve the main plugin - //file or the file doesn't have a "Version" header. - if ( empty($info->version) ) { - do_action( - 'puc_api_error', - new \WP_Error( - 'puc-no-plugin-version', - 'Could not find the version number in the repository.' - ), - null, null, $this->slug - ); - return null; - } - - //Try parsing readme.txt. If it's formatted according to WordPress.org standards, it will contain - //a lot of useful information like the required/tested WP version, changelog, and so on. - if ( $this->readmeTxtExistsLocally() ) { - $this->setInfoFromRemoteReadme($ref, $info); - } - - //The changelog might be in a separate file. - if ( empty($info->sections['changelog']) ) { - $info->sections['changelog'] = $api->getRemoteChangelog($ref, $this->package->getAbsoluteDirectoryPath()); - if ( empty($info->sections['changelog']) ) { - $info->sections['changelog'] = __('There is no changelog available.', 'plugin-update-checker'); - } - } - - if ( empty($info->last_updated) ) { - //Fetch the latest commit that changed the tag or branch and use it as the "last_updated" date. - $latestCommitTime = $api->getLatestCommitTime($ref); - if ( $latestCommitTime !== null ) { - $info->last_updated = $latestCommitTime; - } - } - - $info = apply_filters($this->getUniqueName('request_info_result'), $info, null); - return $info; - } - - /** - * Check if the currently installed version has a readme.txt file. - * - * @return bool - */ - protected function readmeTxtExistsLocally() { - return $this->package->fileExists($this->api->getLocalReadmeName()); - } - - /** - * Copy plugin metadata from a file header to a Plugin Info object. - * - * @param array $fileHeader - * @param Plugin\PluginInfo $pluginInfo - */ - protected function setInfoFromHeader($fileHeader, $pluginInfo) { - $headerToPropertyMap = array( - 'Version' => 'version', - 'Name' => 'name', - 'PluginURI' => 'homepage', - 'Author' => 'author', - 'AuthorName' => 'author', - 'AuthorURI' => 'author_homepage', - - 'Requires WP' => 'requires', - 'Tested WP' => 'tested', - 'Requires at least' => 'requires', - 'Tested up to' => 'tested', - - 'Requires PHP' => 'requires_php', - ); - foreach ($headerToPropertyMap as $headerName => $property) { - if ( isset($fileHeader[$headerName]) && !empty($fileHeader[$headerName]) ) { - $pluginInfo->$property = $fileHeader[$headerName]; - } - } - - if ( !empty($fileHeader['Description']) ) { - $pluginInfo->sections['description'] = $fileHeader['Description']; - } - } - - /** - * Copy plugin metadata from the remote readme.txt file. - * - * @param string $ref GitHub tag or branch where to look for the readme. - * @param Plugin\PluginInfo $pluginInfo - */ - protected function setInfoFromRemoteReadme($ref, $pluginInfo) { - $readme = $this->api->getRemoteReadme($ref); - if ( empty($readme) ) { - return; - } - - if ( isset($readme['sections']) ) { - $pluginInfo->sections = array_merge($pluginInfo->sections, $readme['sections']); - } - if ( !empty($readme['tested_up_to']) ) { - $pluginInfo->tested = $readme['tested_up_to']; - } - if ( !empty($readme['requires_at_least']) ) { - $pluginInfo->requires = $readme['requires_at_least']; - } - if ( !empty($readme['requires_php']) ) { - $pluginInfo->requires_php = $readme['requires_php']; - } - - if ( isset($readme['upgrade_notice'], $readme['upgrade_notice'][$pluginInfo->version]) ) { - $pluginInfo->upgrade_notice = $readme['upgrade_notice'][$pluginInfo->version]; - } - } - - /** - * Add icons from the currently installed version to a Plugin Info object. - * - * The icons should be in a subdirectory named "assets". Supported image formats - * and file names are described here: - * @link https://developer.wordpress.org/plugins/wordpress-org/plugin-assets/#plugin-icons - * - * @param Plugin\PluginInfo $pluginInfo - */ - protected function setIconsFromLocalAssets($pluginInfo) { - $icons = $this->getLocalAssetUrls(array( - 'icon.svg' => 'svg', - 'icon-256x256.png' => '2x', - 'icon-256x256.jpg' => '2x', - 'icon-128x128.png' => '1x', - 'icon-128x128.jpg' => '1x', - )); - - if ( !empty($icons) ) { - //The "default" key seems to be used only as last-resort fallback in WP core (5.8/5.9), - //but we'll set it anyway in case some code somewhere needs it. - reset($icons); - $firstKey = key($icons); - $icons['default'] = $icons[$firstKey]; - - $pluginInfo->icons = $icons; - } - } - - /** - * Add banners from the currently installed version to a Plugin Info object. - * - * The banners should be in a subdirectory named "assets". Supported image formats - * and file names are described here: - * @link https://developer.wordpress.org/plugins/wordpress-org/plugin-assets/#plugin-headers - * - * @param Plugin\PluginInfo $pluginInfo - */ - protected function setBannersFromLocalAssets($pluginInfo) { - $banners = $this->getLocalAssetUrls(array( - 'banner-772x250.png' => 'high', - 'banner-772x250.jpg' => 'high', - 'banner-1544x500.png' => 'low', - 'banner-1544x500.jpg' => 'low', - )); - - if ( !empty($banners) ) { - $pluginInfo->banners = $banners; - } - } - - /** - * @param array $filesToKeys - * @return array - */ - protected function getLocalAssetUrls($filesToKeys) { - $assetDirectory = $this->package->getAbsoluteDirectoryPath() . DIRECTORY_SEPARATOR . 'assets'; - if ( !is_dir($assetDirectory) ) { - return array(); - } - $assetBaseUrl = trailingslashit(plugins_url('', $assetDirectory . '/imaginary.file')); - - $foundAssets = array(); - foreach ($filesToKeys as $fileName => $key) { - $fullBannerPath = $assetDirectory . DIRECTORY_SEPARATOR . $fileName; - if ( !isset($icons[$key]) && is_file($fullBannerPath) ) { - $foundAssets[$key] = $assetBaseUrl . $fileName; - } - } - - return $foundAssets; - } - } - -endif; diff --git a/vendor/yahnis-elsts/plugin-update-checker/Puc/v5p5/Vcs/Reference.php b/vendor/yahnis-elsts/plugin-update-checker/Puc/v5p5/Vcs/Reference.php deleted file mode 100644 index bbffc25..0000000 --- a/vendor/yahnis-elsts/plugin-update-checker/Puc/v5p5/Vcs/Reference.php +++ /dev/null @@ -1,51 +0,0 @@ -properties = $properties; - } - - /** - * @param string $name - * @return mixed|null - */ - public function __get($name) { - return array_key_exists($name, $this->properties) ? $this->properties[$name] : null; - } - - /** - * @param string $name - * @param mixed $value - */ - public function __set($name, $value) { - $this->properties[$name] = $value; - } - - /** - * @param string $name - * @return bool - */ - public function __isset($name) { - return isset($this->properties[$name]); - } - - } - -endif; diff --git a/vendor/yahnis-elsts/plugin-update-checker/Puc/v5p5/Vcs/ReleaseAssetSupport.php b/vendor/yahnis-elsts/plugin-update-checker/Puc/v5p5/Vcs/ReleaseAssetSupport.php deleted file mode 100644 index d24b3b2..0000000 --- a/vendor/yahnis-elsts/plugin-update-checker/Puc/v5p5/Vcs/ReleaseAssetSupport.php +++ /dev/null @@ -1,83 +0,0 @@ -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/v5p5/Vcs/ReleaseFilteringFeature.php b/vendor/yahnis-elsts/plugin-update-checker/Puc/v5p5/Vcs/ReleaseFilteringFeature.php deleted file mode 100644 index faff106..0000000 --- a/vendor/yahnis-elsts/plugin-update-checker/Puc/v5p5/Vcs/ReleaseFilteringFeature.php +++ /dev/null @@ -1,108 +0,0 @@ - 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/v5p5/Vcs/ThemeUpdateChecker.php b/vendor/yahnis-elsts/plugin-update-checker/Puc/v5p5/Vcs/ThemeUpdateChecker.php deleted file mode 100644 index 5348fc7..0000000 --- a/vendor/yahnis-elsts/plugin-update-checker/Puc/v5p5/Vcs/ThemeUpdateChecker.php +++ /dev/null @@ -1,83 +0,0 @@ -api = $api; - - 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); - } - - public function requestUpdate() { - $api = $this->api; - $api->setLocalDirectory($this->package->getAbsoluteDirectoryPath()); - - $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. - $updateSource = $api->chooseReference($this->branch); - if ( $updateSource ) { - $ref = $updateSource->name; - $update->download_url = $updateSource->downloadUrl; - } else { - do_action( - 'puc_api_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 ' - . 'to the repository or it\'s configured incorrectly.' - ), - null, null, $this->slug - ); - $ref = $this->branch; - } - - //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 = Utils::findNotEmpty(array( - $remoteHeader['Version'], - Utils::get($updateSource, 'version'), - )); - - //The details URL defaults to the Theme URI header or the repository URL. - $update->details_url = Utils::findNotEmpty(array( - $remoteHeader['ThemeURI'], - $this->package->getHeaderValue('ThemeURI'), - $this->metadataUrl, - )); - - if ( empty($update->version) ) { - //It looks like we didn't find a valid update after all. - $update = null; - } - - $update = $this->filterUpdateResult($update); - return $update; - } - } - -endif; diff --git a/vendor/yahnis-elsts/plugin-update-checker/Puc/v5p5/Vcs/VcsCheckerMethods.php b/vendor/yahnis-elsts/plugin-update-checker/Puc/v5p5/Vcs/VcsCheckerMethods.php deleted file mode 100644 index a732110..0000000 --- a/vendor/yahnis-elsts/plugin-update-checker/Puc/v5p5/Vcs/VcsCheckerMethods.php +++ /dev/null @@ -1,59 +0,0 @@ -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/Puc/v5p5/WpCliCheckTrigger.php b/vendor/yahnis-elsts/plugin-update-checker/Puc/v5p5/WpCliCheckTrigger.php deleted file mode 100644 index 695ca93..0000000 --- a/vendor/yahnis-elsts/plugin-update-checker/Puc/v5p5/WpCliCheckTrigger.php +++ /dev/null @@ -1,84 +0,0 @@ -componentType = $componentType; - $this->scheduler = $scheduler; - - if ( !defined('WP_CLI') || !class_exists(WP_CLI::class, false) ) { - return; //Nothing to do if WP-CLI is not available. - } - - /* - * We can't hook directly into wp_update_plugins(), but we can hook into the WP-CLI - * commands that call it. We'll use the "before_invoke:xyz" hook to trigger update checks. - */ - foreach ($this->getRelevantCommands() as $command) { - WP_CLI::add_hook('before_invoke:' . $command, [$this, 'triggerUpdateCheckOnce']); - } - } - - private function getRelevantCommands() { - $result = []; - foreach (['status', 'list', 'update'] as $subcommand) { - $result[] = $this->componentType . ' ' . $subcommand; - } - return $result; - } - - /** - * Trigger a potential update check once. - * - * @param mixed $input - * @return mixed The input value, unchanged. - * @internal This method is public so that it can be used as a WP-CLI hook callback. - * It should not be called directly. - * - */ - public function triggerUpdateCheckOnce($input = null) { - if ( $this->wasCheckTriggered ) { - return $input; - } - - $this->wasCheckTriggered = true; - $this->scheduler->maybeCheckForUpdates(); - - return $input; - } -} \ No newline at end of file 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 deleted file mode 100644 index 649db4f..0000000 --- a/vendor/yahnis-elsts/plugin-update-checker/css/puc-debug-bar.css +++ /dev/null @@ -1,70 +0,0 @@ -.puc-debug-bar-panel-v5 pre { - margin-top: 0; -} - -/* Style the debug data table to match "widefat" table style used by WordPress. */ -table.puc-debug-data { - width: 100%; - clear: both; - margin: 0; - - border-spacing: 0; - background-color: #f9f9f9; - - border-radius: 3px; - border: 1px solid #dfdfdf; - border-collapse: separate; -} - -table.puc-debug-data * { - word-wrap: break-word; -} - -table.puc-debug-data th { - width: 11em; - padding: 7px 7px 8px; - text-align: left; - - font-family: "Georgia", "Times New Roman", "Bitstream Charter", "Times", serif; - font-weight: 400; - font-size: 14px; - line-height: 1.3em; - text-shadow: rgba(255, 255, 255, 0.804) 0 1px 0; -} - -table.puc-debug-data td, table.puc-debug-data th { - border-width: 1px 0; - border-style: solid; - - border-top-color: #fff; - border-bottom-color: #dfdfdf; - - text-transform: none; -} - -table.puc-debug-data td { - color: #555; - font-size: 12px; - padding: 4px 7px 2px; - vertical-align: top; -} - -.puc-ajax-response { - border: 1px solid #dfdfdf; - border-radius: 3px; - padding: 0.5em; - margin: 5px 0; - background-color: white; -} - -.puc-ajax-nonce { - display: none; -} - -.puc-ajax-response dt { - margin: 0; -} - -.puc-ajax-response dd { - margin: 0 0 1em; -} diff --git a/vendor/yahnis-elsts/plugin-update-checker/js/debug-bar.js b/vendor/yahnis-elsts/plugin-update-checker/js/debug-bar.js deleted file mode 100644 index 80f53f1..0000000 --- a/vendor/yahnis-elsts/plugin-update-checker/js/debug-bar.js +++ /dev/null @@ -1,54 +0,0 @@ -jQuery(function($) { - - function runAjaxAction(button, action) { - button = $(button); - var panel = button.closest('.puc-debug-bar-panel-v5'); - var responseBox = button.closest('td').find('.puc-ajax-response'); - - responseBox.text('Processing...').show(); - $.post( - ajaxurl, - { - action : action, - uid : panel.data('uid'), - _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-v5 input[name="puc-check-now-button"]').on('click', function() { - runAjaxAction(this, 'puc_v5_debug_check_now'); - return false; - }); - - $('.puc-debug-bar-panel-v5 input[name="puc-request-info-button"]').on('click', function() { - runAjaxAction(this, 'puc_v5_debug_request_info'); - return false; - }); - - - // 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-v5'); - panels.each(function() { - var panel = $(this); - var uid = panel.data('uid'); - var target = panel.closest('.debug-menu-target'); - - //Change the panel wrapper ID. - target.attr('id', 'debug-menu-target-puc-' + uid); - - //Change the menu link ID as well and point it at the new target ID. - $('#debug-bar-menu').find('.puc-debug-menu-link-' + uid) - .closest('.debug-menu-link') - .attr('id', 'debug-menu-link-puc-' + uid) - .attr('href', '#' + target.attr('id')); - }); -}); \ No newline at end of file diff --git a/vendor/yahnis-elsts/plugin-update-checker/languages/plugin-update-checker-ca.mo b/vendor/yahnis-elsts/plugin-update-checker/languages/plugin-update-checker-ca.mo deleted file mode 100644 index 59645faba22e5f3b1358ef076a01d5a7fa3aa534..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1186 zcmZ`&%We}f6g5yD3JU~l7MF@jAn=eGUhPB?f>02mg$Po_u5xE?6T{RV*`7X-koW+0 zhy^>uFR+0P5@LzOC$M16M{p*S5}sDhoY=mPbM5P|$7Ws%jDx^&U;rEjo&)uG2OI_7 z0|a~qW`XZO7dWy8}I`73-}WF&`jfh1$+|or(n2@ z$6kD4Ca@&-k5_~^FyUI~c=Se`J*IW*s48<6*o(o49h3HCEM+5QhFsVosZFH|wN`K> zR?K5#x6H%=Hi*EEd{CkCG&|>KMHn%aMK#ohf(`}GTqVO>w8_qEYsjusZ87I}jgak^ z1b=z=Y*pmY6Da4vZbKUgT;Ekp3VMIKk87Fp(ccPYmReZ*Oiw{rQQ zQJGG}$>w0>q|R3V?m+e&tAI-6bvUP#wByS%j%9Lz;>&3}Inz$sZ5YaXys7Jor*;dn zy&#i|6wjye#l~(4XI!Zv%K@v6lv>NTmKUcY;;7x~Srga|VW$KqCtXwwgL#J#*X-o9%M(OOP zBClzLpCXloN)jJ<-gN!%O{ zB>(p8)gMt|<1=e`ScRtXSByfRLdUq(KfSFJ6!629vGE!UXnOYH)9c?7LY#*cWS6#% cwcF+j&+0z~QHeLF5H1o+|4uN~nyX0s0EpISt^fc4 diff --git a/vendor/yahnis-elsts/plugin-update-checker/languages/plugin-update-checker-cs_CZ.mo b/vendor/yahnis-elsts/plugin-update-checker/languages/plugin-update-checker-cs_CZ.mo deleted file mode 100644 index ac6d20ea77cb6c6ad2aa9204312c53c86078e08c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1077 zcmZWoO>fgc5H(P7$gP|Z>S3s;)T*rGq^c+m;iI8N6={juv{b!B8+#f%adxfUb=pSo z8#o~jobm&Z`UiRnH;&x-8(f*KlYWSm#&5^_=Iz_H=g)(guMUm-6mt}Ho6z`_!zIqr z{4)hme4&`9IH#ym{H9o{DPi$ zOoWgoStk}?Vw2#^8xVK`15`Se0^~7R#)6)bXtx_1{8vquZj-YVj0Ee~bs9=`F)(Z^ zWCyvvKapkmk=VpxVHZ=W4BOV7IArTtN3*8%q0soyWHp7{kTv#}G<_(0rDx1rWn~Xa zp1-=X?5%hn5!o&dVta&JJWGYrs=xAl*`raYb8T2taiJ4#r1IfFcFoW4K?Hle8z%5# zKsg4{Yi(0Eko}ibBRU!HAZsG;`%oLwIxOZuzO!}`2TNBh9|Fy4M}1DW(aJMa6z~rO{OP zo11Lynr9DmjEZfDK!&mC_^{TFP2rH$Wgyv}%v6AO&J)rLbc_5QvUey@<+osIz#uXv z)qb&#;UIv|5!G zR$8Zi>1jD2yrF_z1yO_4nMeAxaB00^k4vA49LZK{lU6F7qaIz5l8GE}1H5N4ay#S! zQp-%6LZBG`fKY0arDA;HIy*QN<57QnG3|zl#@P)4s<`Zt9XS|}Y)cHMy^`6Vyo*7P19Tgjwux$VXt&C1zNV&`UD?ilNF4Yl zICDerA0Tnu9f>>QUxAmVTRUOp<@vKee}1uF{@kDY6rkM!9s;|-UEl*ywy(fF;2S`| z4`3en4K#tjfGGPng5Vc01Rj*}tsqzgAA%o&KY~N>XYdp7PcTx)?Izv`gE`>#c%;%Z z=~mPlaBoO`W2qRW(z6RX1GY@ckv7yDNS$$RGLk1!pfh*m{CqBu%cmzSdDC_fzu32xChlg(SsiwzG zik~&61>Ty%_PAB)N~jWcRep!hPmN98u5v!1Znx3pM)xd?r#a!z{8deTEILSHoGs%F|hy=lDlbzO2ta4E_O#F(`Ea diff --git a/vendor/yahnis-elsts/plugin-update-checker/languages/plugin-update-checker-de_DE.mo b/vendor/yahnis-elsts/plugin-update-checker/languages/plugin-update-checker-de_DE.mo deleted file mode 100644 index 0734cae2dc9b76d41f5f6f99b1380ec2f685e1be..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 980 zcmZuv&2AGh7+j!$6i)Plgi!Sn35g$h$wp9>4M9MfqKXtEnj&tIll`(;vauuEn^K9_ z;K+>wJOH=e`U)I4apXA|chjbourxcLcR$aL?fJ91@+H8y0^9;Rz%}4A;Kz61KJWv$ z4*UWL_zTrP?cpW?f-vECFuYrGp(Rw^k1}lK~;K#+1 zPM?>3^@0@d)0~aXv?4tsH_j~0@*>R?p^|f%<#Ld77_`PboX|)cDrSjvY=hpI4f`&o zX*iZDVih)w9nRIf$rqP8yTPf*77=s_*2)zB#3@jUaJ{ZC&MKYCpD zb)1n1$`gw*|dEss6VZzTU9UMR*Qx-jz)0iqd+dJ*0 z@hGfST3R_)5I&f}q2o{P;VhS#YWUMLmR)nNwXa55Z@DK1O@Xgwd6E%mf_560;``&xsdvEsdb7Q+6 zo(~`&LF(>+XJ?=a{UP4Jg%IRt$T;LrNComQWFB(<9nWLXEvMi0yj|#vIREwD!2cig z=Qz)fdEVF1PoTep{s+1Yt>4FAwJjQVXho%zb(-7=?bX{N6%=cdiW+S$TOv^{;%huk z_;MnA@0PqH)w&!80D}x7C2hFLG>uQ_anG~`b&{+VOER%Z#Ml**Vx87Rs$(Tdt&l@Z z=+_`rJ5k_`=&H(+Cioa?3M10hSc2fnYsSRE_c*-hWkUOJazJCJOJ*H1id@&eS4-7x z(J<_KlYKd084by?!C=_1&r_#sVHkzsg#b@!fosF+DVI9oMx_ziAMKGn$hY$c_IbWR_Ivxg-OIP~ zO?#AY04`e@ZwXcxd==nb`v-n6ZQmXO_w3jokw{95*B9qU4Ndt$sj8$A5(V#dz}$$t zX0ns;SeD(gQ!Py8R{a{gJi<9*DY(;c=IX0zQlBGOh*HpTyBa+xQj=B<- z-PrJ2k#xR7Q{~cE>{B5{I%sV{H59dt>F8*3GEohl#9H{v@i&ve)s$$)hF#@abhv3p zx=NdRA=W0MrKR$cC@Q*xAV*xETAJ?E-j+pd+&TL+@U3DE7LK zB2R7K_v|B7>Elvt=38**_krE9zZR>1h2qYdKRnH08^-4a6u!-()>gg^F2zS`f3kay zb>DWK>f-hs6u6fz%O33eXYqu0(C!HyMe<%@aG&0=W8B^?a@<+~FNpuNW0h tD1$K;9ibq(uDfRr)=})aL7zF{w;=S(@yJe5J=N&R+}l`47fg?Q?|%dqbwmIF diff --git a/vendor/yahnis-elsts/plugin-update-checker/languages/plugin-update-checker-es_AR.mo b/vendor/yahnis-elsts/plugin-update-checker/languages/plugin-update-checker-es_AR.mo deleted file mode 100644 index 85afecd344184a07c3ff0117b87066af6850078c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1140 zcmZ`&O>Yx15H(Oh3I{~bNDP%KQ3)?e3R1OE4ke_hqJ@a2sJF=7ohGImJF>lL%WvR@ z;Ep(Q1ys0DpicaPyK7ZSW>og5QBZ06zf2e&>o1OW-4L1N;eG2mc1Ig6HRixC8Ej;WAm5 z@x*6=BXMR7dj`aHQ;2Q_N=3Pl&Zj9bO-F1v?pUJ87R}|%=Sr*mCn>|#*x@I z`^FxasRL{ffgSmvLhfl{(JzQFU>aq4UmFTKWIVS@h7V}W&TDJP?onZ}=ueH1Z6?75 z@0QK86nX-s9M}!Dfxx{}#iXG3%zaYJqK__WKwOn%Py;7OqI>` z&GvchT2!sHtO;y_>>iB}CGcT*Fv^rRjiT?)b7*dN*W}8%om0l|v6F3+*i@T-Oe?!O zRCeT3HtbZeE~bv_PzGjOdeJ)8FV03Rw1?`T6Q>cc2{A%G!4`dsU+ko({EIQ{$pC7+sScm$Z;R} z9eyZNqK3QLdP=n)S)(Uo+s1&V#n+6IY19;B59^tjCtnOsd}57FG^~$5FZ$!}72lxoiWYRWOg{3oR?75F~?_B?$o%tZJZUT3KE^rHY2NdfYa0mDf z5bz6_1O5U{;Pw?E+Taba1iuG=1bza9{q{8>7Qjc~2KY0$4*mmP0ng3|aSz-D!)3g# z;)%}!N8S2|NW8AoEv z>=}DtCJwMc1a{7<-l&J4Fv9_j(zvU@Z_l)#7K(I`{eG>X1E&!M^1U6sq{c1{_;%TBgUVpDDUF)i=t zP}!Ex*sxQ(_-UOutnL`j2USVaLb0A;*2> zcle=9i5l)`>nYWKWQ`t=Z5soc7GE<;CQ(z2J*=l2lxoiWYRWOg{3oR?75F~?_B?$o%tZJZUT3KE^rHY2NdfYa0mDf z5bz6_1O5U{;Pw?E+Taba1iuG=1bza9{q{8>7Qjc~2KY0$4*mmP0ng3|aSz-D!)3g# z;)%}!N8S2|NW8AoEv z>=}DtCJwMc1a{7<-l&J4Fv9_j(zvU@Z_l)#7K(I`{eG>X1E&!M^1U6sq{c1{_;%TBgUVpDDUF)i=t zP}!Ex*sxQ(_-UOutnL`j2USVaLb0A;*2> zcle=9i5l)`>nYWKWQ`t=Z5soc7GE<;CQ(z2J*=l2lxoiWYRWOg{3oR?75F~?_B?$o%tZJZUT3KE^rHY2NdfYa0mDf z5bz6_1O5U{;Pw?E+Taba1iuG=1bza9{q{8>7Qjc~2KY0$4*mmP0ng3|aSz-D!)3g# z;)%}!N8S2|NW8AoEv z>=}DtCJwMc1a{7<-l&J4Fv9_j(zvU@Z_l)#7K(I`{eG>X1E&!M^1U6sq{c1{_;%TBgUVpDDUF)i=t zP}!Ex*sxQ(_-UOutnL`j2USVaLb0A;*2> zcle=9i5l)`>nYWKWQ`t=Z5soc7GE<;CQ(z2J*=l2lxoiWYRWOg{3oR?75F~?_B?$o%tZJZUT3KE^rHY2NdfYa0mDf z5bz6_1O5U{;Pw?E+Taba1iuG=1bza9{q{8>7Qjc~2KY0$4*mmP0ng3|aSz-D!)3g# z;)%}!N8S2|NW8AoEv z>=}DtCJwMc1a{7<-l&J4Fv9_j(zvU@Z_l)#7K(I`{eG>X1E&!M^1U6sq{c1{_;%TBgUVpDDUF)i=t zP}!Ex*sxQ(_-UOutnL`j2USVaLb0A;*2> zcle=9i5l)`>nYWKWQ`t=Z5soc7GE<;CQ(z2J*=l z*dvxK*??HlF8K%e0X~8=nY2w+Vd=~nd+y`hJJ-KwXFdq5>%eWG3)}$S0mb?T+ycG> z1pET#fWJT!xOqv4Hh3K@!SBHzfu8_jzjZ~31@Ixb0saiGga3e+!Lu_$+yQsNa2c=5 zc;d6bk+?cO5#ri}3!UTD8gQ~pJJwM?N>yMlx&wAh+LN)A43z0}X8WY}l+M(4#*x@G zyTaq4UmFTKWIVG>hWBZYo!8co-J!x_-k%sD+f;%J z-YuJFDf9$NIj|dQ1A#jyib+B5sr$H=c^_TWfWpqF%tsU~6;(%~r!Pr z5hu&W$Vr`*&P(}<_jFN+deYHxRu^TxMzx3WqsOxPuv)FGp>?_Hv+S}O##C8f zU2mVou0_>K%bLI@$nN0?Q34-?2ct}B(tgCyPIaJqw21R^BcCYGBNYZQMNy@b29(>znmPQ7>Mb z_YB=_Qf;Ae7GT5XF5yt*2D`ku`cewrvb(T71nYnM6%7_OPCcdHmJj#3$C+M8o>%%e+7Ofst2a za^6$r2$xpb)HJaV$DhungD{UvkdITAL;K$2lxoiWYRWOg{3oR?75F~?_B?$o%tZJZUT3KE^rHY2NdfYa0mDf z5bz6_1O5U{;Pw?E+Taba1iuG=1bza9{q{8>7Qjc~2KY0$4*mmP0ng3|aSz-D!)3g# z;)%}!N8S2|NW8AoEv z>=}DtCJwMc1a{7<-l&J4Fv9_j(zvU@Z_l)#7K(I`{eG>X1E&!M^1U6sq{c1{_;%TBgUVpDDUF)i=t zP}!Ex*sxQ(_-UOutnL`j2USVaLb0A;*2> zcle=9i5l)`>nYWKWQ`t=Z5soc7GE<;CQ(z2J*=l2lxoiWYRWOg{3oR?75F~?_B?$o%tZJZUT3KE^rHY2NdfYa0mDf z5bz6_1O5U{;Pw?E+Taba1iuG=1bza9{q{8>7Qjc~2KY0$4*mmP0ng3|aSz-D!)3g# z;)%}!N8S2|NW8AoEv z>=}DtCJwMc1a{7<-l&J4Fv9_j(zvU@Z_l)#7K(I`{eG>X1E&!M^1U6sq{c1{_;%TBgUVpDDUF)i=t zP}!Ex*sxQ(_-UOutnL`j2USVaLb0A;*2> zcle=9i5l)`>nYWKWQ`t=Z5soc7GE<;CQ(z2J*=l z*dvxK*??HlF8K%e0X~8=nY2w+Vd=~nd+y`hJJ-KwXFdq5>%eWG3)}$S0mb?T+ycG> z1pET#fWJT!xOqv4Hh3K@!SBHzfu8_jzjZ~31@Ixb0saiGga3e+!Lu_$+yQsNa2c=5 zc;d6bk+?cO5#ri}3!UTD8gQ~pJJwM?N>yMlx&wAh+LN)A43z0}X8WY}l+M(4#*x@G zyTaq4UmFTKWIVG>hWBZYo!8co-J!x_-k%sD+f;%J z-YuJFDf9$NIj|dQ1A#jyib+B5sr$H=c^_TWfWpqF%tsU~6;(%~r!Pr z5hu&W$Vr`*&P(}<_jFN+deYHxRu^TxMzx3WqsOxPuv)FGp>?_Hv+S}O##C8f zU2mVou0_>K%bLI@$nN0?Q34-?2ct}B(tgCyPIaJqw21R^BcCYGBNYZQMNy@b29(>znmPQ7>Mb z_YB=_Qf;Ae7GT5XF5yt*2D`ku`cewrvb(T71nYnM6%7_OPCcdHmJj#3$C+M8o>%%e+7Ofst2a za^6$r2$xpb)HJaV$DhungD{UvkdITAL;K$2lxoiWYRWOg{3oR?75F~?_B?$o%tZJZUT3KE^rHY2NdfYa0mDf z5bz6_1O5U{;Pw?E+Taba1iuG=1bza9{q{8>7Qjc~2KY0$4*mmP0ng3|aSz-D!)3g# z;)%}!N8S2|NW8AoEv z>=}DtCJwMc1a{7<-l&J4Fv9_j(zvU@Z_l)#7K(I`{eG>X1E&!M^1U6sq{c1{_;%TBgUVpDDUF)i=t zP}!Ex*sxQ(_-UOutnL`j2USVaLb0A;*2> zcle=9i5l)`>nYWKWQ`t=Z5soc7GE<;CQ(z2J*=l2lxoiWYRWOg{3oR?75F~?_B?$o%tZJZUT3KE^rHY2NdfYa0mDf z5bz6_1O5U{;Pw?E+Taba1iuG=1bza9{q{8>7Qjc~2KY0$4*mmP0ng3|aSz-D!)3g# z;)%}!N8S2|NW8AoEv z>=}DtCJwMc1a{7<-l&J4Fv9_j(zvU@Z_l)#7K(I`{eG>X1E&!M^1U6sq{c1{_;%TBgUVpDDUF)i=t zP}!Ex*sxQ(_-UOutnL`j2USVaLb0A;*2> zcle=9i5l)`>nYWKWQ`t=Z5soc7GE<;CQ(z2J*=l2lxoiWYRWOg{3oR?75F~?_B?$o%tZJZUT3KE^rHY2NdfYa0mDf z5bz6_1O5U{;Pw?E+Taba1iuG=1bza9{q{8>7Qjc~2KY0$4*mmP0ng3|aSz-D!)3g# z;)%}!N8S2|NW8AoEv z>=}DtCJwMc1a{7<-l&J4Fv9_j(zvU@Z_l)#7K(I`{eG>X1E&!M^1U6sq{c1{_;%TBgUVpDDUF)i=t zP}!Ex*sxQ(_-UOutnL`j2USVaLb0A;*2> zcle=9i5l)`>nYWKWQ`t=Z5soc7GE<;CQ(z2J*=l z*dvxK*??HlF8K%e0X~8=nY2w+Vd=~nd+y`hJJ-KwXFdq5>%eWG3)}$S0mb?T+ycG> z1pET#fWJT!xOqv4Hh3K@!SBHzfu8_jzjZ~31@Ixb0saiGga3e+!Lu_$+yQsNa2c=5 zc;d6bk+?cO5#ri}3!UTD8gQ~pJJwM?N>yMlx&wAh+LN)A43z0}X8WY}l+M(4#*x@G zyTaq4UmFTKWIVG>hWBZYo!8co-J!x_-k%sD+f;%J z-YuJFDf9$NIj|dQ1A#jyib+B5sr$H=c^_TWfWpqF%tsU~6;(%~r!Pr z5hu&W$Vr`*&P(}<_jFN+deYHxRu^TxMzx3WqsOxPuv)FGp>?_Hv+S}O##C8f zU2mVou0_>K%bLI@$nN0?Q34-?2ct}B(tgCyPIaJqw21R^BcCYGBNYZQMNy@b29(>znmPQ7>Mb z_YB=_Qf;Ae7GT5XF5yt*2D`ku`cewrvb(T71nYnM6%7_OPCcdHmJj#3$C+M8o>%%e+7Ofst2a za^6$r2$xpb)HJaV$DhungD{UvkdITAL;K$mQ_tX!08MILH_4soF=HQY2)>b;uw zdPS|CiLzl66*kv37#%ueT?g!tl`B3eu~99!!4m8t^drg#;awKwS$L1a+fhF33&J2k zBbye>v0L_dUl_1_!S(eAeL;VJkelSGVI|FFnsB3Z1YgZctY~`f$>e<+tcxU3BYIgS z+%K!8Vf4#dlh*_*3BD8&oYRb1O#}_bvZ_WJTBWY^V|~;cQI*e6Oy{O1rpAsI4E-QC zs-zJT238x`#E9qSRwLoD9B|*VPK6noEse9nQJ*tf6`GC7vZ}fZ4MwZu zD0_3T@#CW#X1B@5BH7ztuORM>xV2jLi+l1=f3@F`b_U@Vf-R`G-B$m$|9^wdU*s>7 C2(8ip diff --git a/vendor/yahnis-elsts/plugin-update-checker/languages/plugin-update-checker-fr_CA.mo b/vendor/yahnis-elsts/plugin-update-checker/languages/plugin-update-checker-fr_CA.mo deleted file mode 100644 index 24639b694e7ba21e2b5f9997b9f12d2d831ac69a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1208 zcmZuwO>Y}F5M>&-1=K^)9{T|d3>Zk!aJ##85MxybNff&LJ!fDKMyPa&$<1lrsRn<7q_YSWChrKqFfjXPxdlxFOM zc9z_TT8pi4VT5Rx0=(tjbB(E>CsM_c{Zv~B99<|T1-&cxc`jQad0PV#doyHHQ*_j3 zoru1754nu;ppp+3DvPB!xhRZW=Gp0gKaf4oDk2kk56%VUX?9a)nasB-yIG|9mua4+ zFqA*=Ot%@Y?RI3E%PglXExyiWdINTcsBxplEC;Nn1$B-Nj`r3fvLx;FoQ-Uw9GumN z7Wr}fsy0g7ZhJvKaNIo}?8}|ComV!D*vmazx=Pz|K|3cpc7BxKvSqKL^9A)CS2|Lj zq{%k^ESB=F3S6r=DJV%gebabl{uqVi|VxZd)2mcduExMcEhKwf}wB_>y}I zSp_Y0txo@r&rY4M!l4eapy9APLq+?eP?k zF)7{j)~a{~jr_28=aLXszMS-ticFDAM?5%x>GeqCr5X-2)dAo0U+EzPivvUU?U zks{TUjh*jWW$@nSmKTOp=}|W|+S-OVL<)_cG3N7DIL2GGu9>kh zylMa(YY-0?$#&imXoc4E^6>}L+J(@DYE@L{FPASLou;Y5sci}?VQ+d1R4EshMJY0DWU2&l2I$v2KbMK|0U|;#BAXDl-5v5>kmhg#p{q2ilDF zG=Mae0WCN$eC}X&&doBPB4jEbNDW?kg)=LlaSS80P8toS4~1gRor&nQO9%WHO_u%@ z=NWhdh2Ma6tl7ud^H#!l%ly$aEiYe*PaRe|TV39?C_H)KuP8WzT3B7=Vey0NLiGIE zldu+sB;?yTl7-i+bql4gP1VW80C^Y1Fro_Ni8QdiyVYKS7peDIG(SHcj{`e0N(8YP zE?3S%BIw)R+ID55wXu5PyBdU*rqLd?=iQ@>40=5D^O+J-*NfY*4t-;%yT+F;bXI8B zN6S}rY!ayl5iIRVUwOyZQKJ>!*a$iX6X~HAgh7q|DVO}EaF_|7Mi2y*j>@f2e9hRQ zi$K%$(b6?)^`e?IZ9LMj4AsZ=i}<%Dw=p(LTM?AL&a=P4qp`7xYfI-N==JJ7toIJ1 z>eE_GOqFo-l7)Fydfb#TmC3>S>g(3#r9)8IIPH*49+J@t+dVz8vM;IS6gn76N6*tQ zuuo=KOM(9N@$(S~5P6*I$*vX(5}YW{gpf#=87-#`4Vg82>hyR>jZan7ItO$fTy955 o^GQ$dXrxafAE8os-pQ0!(Rp-9s3)yWJzYdzPT#&tFf|;ozeSTj4gdfE diff --git a/vendor/yahnis-elsts/plugin-update-checker/languages/plugin-update-checker-hu_HU.mo b/vendor/yahnis-elsts/plugin-update-checker/languages/plugin-update-checker-hu_HU.mo deleted file mode 100644 index 4789ef1da358b7fdef2879615c49eac1fb2dad98..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 982 zcmZuvO>fgc5M7{v6i#qKAPz$$#7DIzPDNE5f+!)S6)8m2MckroGO^v*yVmYHB@w@X zTMt~gl@mR1LgEit{Rfqs~~X?#;8rCB&Z?SFfx$FSrAE}nHY;G7CSLItQBH^1Vg1EO9#TD zVSb1ji!7<29|{>@tb&sz{=Z^b3RXc;>#%J(l4?)Rw5XiKQG>CCjDN zB0%n=NIaOw9)wwMeY>)`vDrR8k?YhdEhQ~V+HsPSb&K!p{WKPlY!uh34cg|mzs6UN z^9pA})VwYGY7oi5gO#1gR^IaGC{dS|y9x)91=m?|mT9F7`BPyq6*lz1aVp(7(<0_; zN+-qxNzYE9Y1SLXJ=3&#N5ah}xOW@J0$VE6eQcG!JSdILot0K zq7;Shhh5s8*J%F=%RlWFy*G{WZ;&7A5be=EUVSD1gFvNatULm~a8 zlo;jFzMfKm>?J1uRnMEzVeKiY&H7o2REtp|>#z-zQ1e>Sq4nWu+GNF8dgRPZMcI&l E0BAre(hWBZYo!8co?Ne#7)JzW+epTRe#dQ`8==#i{P6h(1u`EFE?qRKj2SEvEYE~`;Ym5uhs z>QU@kHLA3%32cJw9_EM=_#oWRGo?+V?7Q2#*>|?b$?P zy8L+FotSj!wY$esv2w|<1GO@O-ip9==)O)Aslh;7XVeHi)8ZB8D7p3XE2%6g3^^Vk zyTf&ImNAXcA2{L0Q|)tW^o}k^cM~%T6HN(P?`)RYlTpdzgY}6nU^brQEu+X3c2CWQ z7ZEv|%`GMv3QnXbb>S?x-j9=(eq;R@QqL2~(0ja?Qqf!_<@lG%`ECD~W#$oVRr~{k C>Q&|d diff --git a/vendor/yahnis-elsts/plugin-update-checker/languages/plugin-update-checker-ja.mo b/vendor/yahnis-elsts/plugin-update-checker/languages/plugin-update-checker-ja.mo deleted file mode 100644 index 941b6ba2f4d759727a71a177592dc432753d6a85..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1454 zcmZ{i&2QX97{&((Ukeo<7li0xh_olLy}PJv>NJQDQdCHU3)`wEqKS8Q*NxYm8hL6ENf=|LPzzz6q_)`xP z@+|Zc=6i<-c>z8Ge;Mw;IXs3x1OFX<0KN@B49`DG$m{Sn9I40?&?Ar@2qAb)9)})- z^w52v)L=|BxI0H{VN6?5l}RqhbQp8$1$fnD(hCF1X2X`Gc|j@-u0IJHgw$=Ypw9iU zPT4&3d^YQIlN<@=g0LOzq(TgG^Oy?BWJ}QDyci}&J>I5OF0n=s+2AztTXip>(vv

?Y+5Q5_Zx+>QQSw1WxG&* zrLezHK%nsfpZ9cg4~#38`f*cCNTU+7K=@3Cu}vkLqX%#+mrMKJtT(ZFrW-cj$W7rV zv{;=R70#L<*`3?;IGcIb$xR=co*aM{%|dP>3?vVbeK7*2U0m0JT0h z!V+FH^0^^o>_yzDWB1!^(Q;aD&hc9@^NoWz$ik)p7GNsIilh2C;c=`mI)HtTFX}R4 z$`jJ2Gc%(z3wH6)_zu}XeWNoRX?eQRTlbkA>em)ACb{=R#4LnYT#lB)ESN^Ys-yh^`RODR#= z7dlz`tI95^Y<*B9>GX4}*TvxWhZ*s ze#7(MH_zQ(`X(=MBYhn3Zh!aV*2)d=(q1F0DqU0QiY}aVx)+uJdoNJ(`CZgsYh=AR y=?qBkY{yP0=y0v7rQ;T9t9u4ClK@z{3ericUi%PFW*e3e!i-y`f+yUy}&sMoC5~HDc}uIo=?CT;4?tL zH((9;33PzdM}+8sx4;to4*U!F0+jJS9ur~}{2hE1{2P1`yuKnt8~g}d`n?6iWpR$; z7iI!i;`ri5h!aaLbuLbK%E^qz)=`nCDzF!WDLW?Z$yiFJ%1k)36H?nsXKIvjB%Yd? zu{&nz02@SLM?R=fcv@TcYa&dU@~oI>LqUg(S8kKx9olB+wKZhNR9dY2T_a@Mm*9|h z*A`g{J%LgV?B?1);CNRtDd_#{zNls0M~5|_u!AX!oPwpY>PYmReZfhP_fz?-QW-DB z$*M7OS!b>Pa3H&mRX`>3E}Ua()*CHZzapF0sL_fW*DltZ^*RjYW8T(f#s9Rs(yZ(@ z(c?l*SPodtW2$Z4-|Fp&Xhii|*P6g4$ib@|*#f@|m-9?%(=I=d^Bg))2OF}rXXljh zV|KD<5}Rr>iK#Wxq4r$fW5Z4b>tgC#PIaJ0)QYZ04g6PK$UDk&uEI2?D5~|d!l_Jd zSU2}E8GKW``cAW5HV2QL^M+PC)VR>z3-H7iF5zyaET&4@-|!Fk)sA(k-_$MZqVmCOx1&*+}D-m~#^V_d%9vU$*R{TijsRlrF2D6#XK@UB`3 zsoC&OZ=WVsE}8aGmaL<&nkZZ9Y{nQ|o0HL8>~J-oSb?4^=YPU%_HDq3eKOUvky0)a z53v?AHYx9p{Ybx{WEt~N#JJjuDr_0`Kt9@5rX0)z2_9fgU=?tis|+sK8EE~VBXmdN gF4LUZ2XdTXY!*|$SiQwsPx$KxgJsRi;?qd{0TG{S#Q*>R diff --git a/vendor/yahnis-elsts/plugin-update-checker/languages/plugin-update-checker-nl_NL.mo b/vendor/yahnis-elsts/plugin-update-checker/languages/plugin-update-checker-nl_NL.mo deleted file mode 100644 index 16dde622ba6040399cc911e0d5ef1c970a541b88..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1211 zcmah|&59F25N>rYShMgp(iFTo-2 zt}U_@dIF^!*v+(oz|pQ^QqcR?eO}9oj}B`FtAI-6JvhhItT$S+epNQFQ==6(u3xG*>vb5)r@X1livMYMwOQG% zqsN6Bv+T2)#Z=pPu(7%)q7l_=U26iHAp1KxvIX7_SMp40(=I=d^Bg+Q`)jhbXXljh zBX)AtBsSG%98+tkL+z!!&xV}}*2UDboa#W0s1@Ca8u+iekav~mT!l$YQB>6P~&2IFTgWfxP-fvvY0Aqf5SiIoh|E9zpj0VX)tIH zxINg88<(32xVEl5>MZqVmCQ9fPwBq3-m~#^b5y?Hwt3Jq{TijsRKQ61D6z9!@UB`3 zsoCJs`aVspTr%mQELlfkHBq+I*^Du`HYcOG*y3tFu>z~Eoc}Si*|z~h_Q^y~hf29f zJjPl~*`&NX_Cx)Ol10oz5#wqrs<36$1NmrEnQ|}>BzTB5fmOh5t}?h_XQ1_ej?f*6 gdrUKCAINcnv6)Z(eD&sQJ?5_;43;%3i%%o*2Pb`M*Z=?k diff --git a/vendor/yahnis-elsts/plugin-update-checker/languages/plugin-update-checker-pt_BR.mo b/vendor/yahnis-elsts/plugin-update-checker/languages/plugin-update-checker-pt_BR.mo deleted file mode 100644 index d1c0f283287da07c7060255756947399fde75ca6..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1014 zcmZuv!EVz)6f{scgcF=V;_y_d5=dPW2P%rAAllGEMM|SKMcksreu>>WyVmYHZ4oE_ zfe%0&fCEQPT#)h`h+lzm97qtXGJgB)+1bhN{J6UG*2B02+yFYjW#BbXj*q|<;1fW= zS6~_V4zz%ufGFqZJntKD3|vFMdZFTNpgW5oypn^Ib=kY}AEddv&Zz?~t zX;s<@N5?eKhKf9vj;+^A*f6D*l%^<=YRH)$k{ru4lP@#&y+d`Z^og1+00#ed~o)yDXkxO01OB=CIb?>xs5u>EJ;;!s3t`_28bUuZiG31#98mK-BNl>mZ7K z9;c<(|MMCZuOqD!JtLLPq|+v(S_kJ<$RUd!%h5s)ORm4UU)$Z;-J07B{Ccgem16~& zvmAaLpSs(5CR5cc58qgJt;627SfBIC?FMYbmWp(os$od$FH={0As(}0Q~Bs>j#Ed0 zzwWQ&OVx@^X*riJ3CZ_s-K;P&6WiL1Y)A^Xh1Rwj&GPUtZQWG#fP!1i`T7H0n26hz zt&l2Tf7GAy*@-r>?WER))bBU@-0Yv?7Y3`1XhDUgiIOgSh&r6qJltA3NF!-z!xb`1 zU&+ab$rmK?+2p;ZWb%%R(LxgA)aF`EK94!`y@Pq^C}taJg*2wI_Pr<5brLBa%W3dR uv0NHSC{;9(zXh@CV~k{HTE@P&w?I3B7+Z&@l4Ogy;7B66h9le{qWB9G2Q7U7 diff --git a/vendor/yahnis-elsts/plugin-update-checker/languages/plugin-update-checker-ru_RU.mo b/vendor/yahnis-elsts/plugin-update-checker/languages/plugin-update-checker-ru_RU.mo deleted file mode 100644 index 50b330e9332d5024e9bf5f931e5b1e76dca7cd7a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1337 zcmZuw&u<$=6dq`R${Y|}xNvxlltO7{+1&&h*4}=9X zJv7OUR;mz!8|uGcN~*d9Q*njM>_5O?z=^+rZ+7zw+L52Xc{|@X?|X0Uzuubpo?*R) zcn8rzypFh!aBG5i6Y&&5h(8gth`$jr;*FOWTL!KGIq*B+$(I@X9r!NtKTa@q4)_nS z3w(cuv3cM(K$kxOo&vu83S*E|3vvcJ!x6*dYQ4IT&S$k+L)p7YYni5E)E7qPtTU8a zQj(L(s5ca9Ak%C>VnZaUxRFYat*VQ+{yefTldmqzOKM8V+NfnyTzdnm7ZnajQB zJ)p7wmMlhOGICvetgW-JWzX;{eSW=m8SR_n^bm`takk(D{w4m~kNnl6Rz7kEpS7Wo7xu zMBw?2R;G+phIej{P|e6&=7Uix64i7sNaxbTtDVby>4>L=%Gadk%c__46E%ov=|*B2 zU-8eRl3JKdN7T+_KQR<~A)eO>|3u_+B+M`(&ug^PLW`7N&h&a7k;3~#n#T)GHyCW= z_taeA$8kWXPm|mFr{W->i{umN$S=gQVxl>Q<%W>fy&lduB3*Q^ ztsbi*h3*a8=$ZTIy20$j@~-{OKC+L2lXAPfPe^~V)9T@#eT?0te8B7vDv)KQ13o-9)+N{JLMh-GwQXgq3H`cx{G|?z%3j!>U_X4doGg p^$6zwr!DW1J9>c)S9aI#RRwYXL(s|fZP{fYnp diff --git a/vendor/yahnis-elsts/plugin-update-checker/languages/plugin-update-checker-sl_SI.mo b/vendor/yahnis-elsts/plugin-update-checker/languages/plugin-update-checker-sl_SI.mo deleted file mode 100644 index df47ca7c0a01cff815ffe3965ee4918e72a600fd..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1203 zcmZWoO>YxN7@k5(CHH_@u9bL+6a=EP>~5kaT4SnW5)?I|RxzkIYhu5#$63#;W@a}b zzoDEE|E0YkRe}?@{($}hjvRaFvtApg%1F;X`|iA7&pWgKe7p8WV0{IA2lRojf!~38 z{Q-Of{0R{70ayn<0v+J`7eefU55W@r8vHNt7jOgi+p9v{0{;!J_dhLoeNBi*uzTQ} z;MZV;%-0n>;U@4&d^!Ij#I*(2ea=^R!ow3fwvNhTqyl@A$>eqDqKQ<0ZrZ7ArF^V&~j_>?MkURy)u~>Ychy7^#jUP2flZM8mj$W?J`4AYTxrv; z56F2Ao#*{MxwGnW1R4EsX5^8kov|_KI$pYPP7MXnNmmEPaDa zh?X_)x$EUdPrfbl$J4a3e3G0xthBbFNsTPF6 zQ|y$Xe5o9dlpn+t1eI2nTb0RmWA|N58vg>JYt-sRX)tX(()6%F(L((y!H&somz$-p zm`Y=p>0k5Ffw4WenK~a+r&I56y>l2xk852pO5yOz!hKenyev*kZrs^fo4JRT?G9S7 zDnpp9h@Hvlkht&BMEU5v3oTx*tXO4F{Zwm5h*{I*ME8m!Zv5guX~VIY|;YsJcM3XG8e7a;khF F{sQ>&EFS;> diff --git a/vendor/yahnis-elsts/plugin-update-checker/languages/plugin-update-checker-tr_TR.mo b/vendor/yahnis-elsts/plugin-update-checker/languages/plugin-update-checker-tr_TR.mo deleted file mode 100644 index 58be2f9306dd0e01aa725c03d583ca53bdd536a0..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1118 zcmZWn&uA(EYi8EL z|3fcT#W_dLkt#u@Tq?V#{trF(&_ANz+WCbT?YG~~&U@c{@6G)4+0q+RH zH>2~*AyOlH>8_q_yQT8Vzs6>7pAB>FBwq5t#2acVW{Y|-k9_N(} z`|M@cW-ixukka~|j*T6;#g@H_&ZpFKoa;zy(BF}ZiF~XAk5n9{lq8Lwsk}0B)A=%_ zWN}QGhR$lct{0!3FD!lDq1N5@xxfoo`HVLfu2NdqI+K6KlLP1T@LY$O((Z11m)pCq z)7F=(85oTSsIm5L78biD4y@}7W$9s|y!x(w8C3#4u^bN+aE;g<#7Y2uh1&iB_Og+~Q(_=q9E~m#-@;IwvA`q&lZxM4* h*%@3qXG)dNj%J6mBiduQgCI)C^*rfJ|1>cX{{#HHSPlRH diff --git a/vendor/yahnis-elsts/plugin-update-checker/languages/plugin-update-checker-uk_UA.mo b/vendor/yahnis-elsts/plugin-update-checker/languages/plugin-update-checker-uk_UA.mo deleted file mode 100644 index 79494e524ebd28dcba540d54c7f4949d5a436508..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1309 zcmZuwO>YxN7#`a6L*`J?a}O_(LZM-{yPHs=HA@94(heN%>IG?f}VQqrO)i<3(}EaKQpuM^S;mXuKm}?6TdL5 z4-lUqT8QI_M+mz{h!cpH2txdcm_+=I2oWD0V{9I{0OY`*fFHiY*zdqkasK07#^!+k z0KW!KPcZfwPy>GiZUIjM{{@0lF3=g$8LrrS7n+;~Zn09Ae7m55^u^L;)2YDX%eD1sCoe$2Pn+DIVUB`^`s3&+!L@NQ+7OpMK zABgZAx7J9d7E<%podLROaa(^rNTOKQ?F&+w(BWe13ZFa3Q<2P;gyQqElXhd-3ux|U ztZP5;t3nDD=~M;OOhq@=YbLph5`HCBD_KAi?-R!?oT=Nv zU>ly6Q=S`!9-TTxcI%!DJ&(R5mynM0#n9h-bRnFz+mhj4@O-*^x1wD1X3v1)f#RR3 zA1L`Q%~eMhzoN%w4#yF|%c!7x&C_^Q71Wj*16nL}tf~5l_rE9*oVn*kI-{wy(^v z_?gTzvs2tJ9u({5b(#0n?2!4jSOhGx51C-cI*DmKm7sfZ|UStu|vFUgWo2?dJ# zgc^qh{C1>$@u>QfL4lPtBz%E^BAdmA{e{1!XIS;LY0s>hQtXC3j-Uzxi-(oXvt)N~ e(TmOhac^_B%Vwy(g_1+_)VeFXzd5TNhy4cu&FZoM diff --git a/vendor/yahnis-elsts/plugin-update-checker/languages/plugin-update-checker-zh_CN.mo b/vendor/yahnis-elsts/plugin-update-checker/languages/plugin-update-checker-zh_CN.mo deleted file mode 100644 index 5236777ef4caecf0cc9162cdcb1f2789f00093ad..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1174 zcmZ`&-)j_C7`?So>(YSwCKmZf$xH1WCuxLb)`+@|#cFibD1CCd*}d7FWODB^_fDcd z#cH8xDJ`@%Auedph=^n*7N0CW_z(0iklJ)-`{slHfM<4MHYIrBaQ1#b&Ue0<*_XS! zZZe!5z$ZW%=ms7E$@v@D1-t_G0B-;Sx<6p72kd}92A>5Ff-ixGz;!SO{{vnDc5X@Q zUVO;dZp8lr?*p%b3B08%&3_6`;x70z@EP!4@KrEm*hc_b+6N)F71$1JYe&*OFsgI% zRau&#F&$D=D+?XU*%^XjkA75KKQ#ixV$tgcsgnx-%kNVyI0q!2;eOYo{&&}?4v#y&t zC5+`Gp-?6eR)-#)mtaL-`*^@~sOldv?Z9|)cS?HlFj`b45*5iuq?q(*{qE7#YB7I0 zGkjursAI3saWi?XtW=nDr3NEbUbY8nf$&u>d5@uycJRW;ah~neC4RqC5>|6T68E^)WNw55v zFtR3W)g#C0M9=FeEXjOo$fMNJde2FDWm<=2bILc?qhc{vl)2(%ukZ8z5_p4(6k(}a zfI4@fpJDOcnfUfneCv<+_s0z1QfuJ`F3o!j|2|)guQgb_vKZHAn?E;NzdcBED2(Tp zn$PD}XTD`|{bB3&QYXvB2Jl|;ka{s-hty{~9(tIPX&%je__WQX0D3N&!QqYmS 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 deleted file mode 100644 index a3f9aca..0000000 --- a/vendor/yahnis-elsts/plugin-update-checker/languages/plugin-update-checker.pot +++ /dev/null @@ -1,49 +0,0 @@ -#, fuzzy -msgid "" -msgstr "" -"Project-Id-Version: plugin-update-checker\n" -"POT-Creation-Date: 2024-10-16 17:23+0300\n" -"PO-Revision-Date: 2016-01-10 20:59+0100\n" -"Last-Translator: \n" -"Language-Team: \n" -"Language: en_US\n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"Plural-Forms: nplurals=2; plural=(n != 1);\n" -"X-Generator: Poedit 3.5\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" - -#: Puc/v5p5/Plugin/Ui.php:130 -msgid "Check for updates" -msgstr "" - -#: Puc/v5p5/Plugin/Ui.php:217 -#, php-format -msgctxt "the plugin title" -msgid "The %s plugin is up to date." -msgstr "" - -#: Puc/v5p5/Plugin/Ui.php:219 -#, php-format -msgctxt "the plugin title" -msgid "A new version of the %s plugin is available." -msgstr "" - -#: Puc/v5p5/Plugin/Ui.php:221 -#, php-format -msgctxt "the plugin title" -msgid "Could not determine if updates are available for %s." -msgstr "" - -#: Puc/v5p5/Plugin/Ui.php:227 -#, php-format -msgid "Unknown update checker status \"%s\"" -msgstr "" - -#: Puc/v5p5/Vcs/PluginUpdateChecker.php:113 -msgid "There is no changelog available." -msgstr "" diff --git a/vendor/yahnis-elsts/plugin-update-checker/load-v5p5.php b/vendor/yahnis-elsts/plugin-update-checker/load-v5p5.php deleted file mode 100644 index 1ce30a1..0000000 --- a/vendor/yahnis-elsts/plugin-update-checker/load-v5p5.php +++ /dev/null @@ -1,34 +0,0 @@ - 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.5'); - //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.5'); -} - diff --git a/vendor/yahnis-elsts/plugin-update-checker/plugin-update-checker.php b/vendor/yahnis-elsts/plugin-update-checker/plugin-update-checker.php deleted file mode 100644 index 0c070a8..0000000 --- a/vendor/yahnis-elsts/plugin-update-checker/plugin-update-checker.php +++ /dev/null @@ -1,10 +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 $unmarkedBlockTypes = array( - 'Code', - ); - - # - # Blocks - # - - protected 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['continuable'])) - { - $Block = $this->{'block'.$CurrentBlock['type'].'Continue'}($Line, $CurrentBlock); - - if (isset($Block)) - { - $CurrentBlock = $Block; - - continue; - } - else - { - if ($this->isBlockCompletable($CurrentBlock['type'])) - { - $CurrentBlock = $this->{'block'.$CurrentBlock['type'].'Complete'}($CurrentBlock); - } - } - } - - # ~ - - $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 ($this->isBlockContinuable($blockType)) - { - $Block['continuable'] = 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['continuable']) and $this->isBlockCompletable($CurrentBlock['type'])) - { - $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; - } - - protected function isBlockContinuable($Type) - { - return method_exists($this, 'block'.$Type.'Continue'); - } - - protected function isBlockCompletable($Type) - { - return method_exists($this, 'block'.$Type.'Complete'); - } - - # - # 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[1])) - { - $class = 'language-'.$matches[1]; - - $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)) - { - $element = strtolower($matches[1]); - - if (in_array($element, $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; - } - } - - 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 = ''; - - # $excerpt is based on the first occurrence of a marker - - while ($excerpt = strpbrk($text, $this->inlineMarkerList)) - { - $marker = $excerpt[0]; - - $markerPosition = strpos($text, $marker); - - $Excerpt = array('text' => $excerpt, 'context' => $text); - - foreach ($this->InlineTypes[$marker] as $inlineType) - { - $Inline = $this->{'inline'.$inlineType}($Excerpt); - - if ( ! isset($Inline)) - { - continue; - } - - # makes sure that the inline belongs to "our" marker - - if (isset($Inline['position']) and $Inline['position'] > $markerPosition) - { - continue; - } - - # sets a default inline position - - if ( ! isset($Inline['position'])) - { - $Inline['position'] = $markerPosition; - } - - # the text that comes before the inline - $unmarkedText = substr($text, 0, $Inline['position']); - - # compile the unmarked text - $markup .= $this->unmarkedText($unmarkedText); - - # compile the inline - $markup .= isset($Inline['markup']) ? $Inline['markup'] : $this->element($Inline['element']); - - # remove the examined text - $text = substr($text, $Inline['position'] + $Inline['extent']); - - continue 2; - } - - # the marker does not belong to an inline - - $unmarkedText = substr($text, 0, $markerPosition + 1); - - $markup .= $this->unmarkedText($unmarkedText); - - $text = substr($text, $markerPosition + 1); - } - - $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 = strlen($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 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 static(); - - 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', - ); -} \ No newline at end of file diff --git a/vendor/yahnis-elsts/plugin-update-checker/vendor/PucReadmeParser.php b/vendor/yahnis-elsts/plugin-update-checker/vendor/PucReadmeParser.php deleted file mode 100644 index a794c49..0000000 --- a/vendor/yahnis-elsts/plugin-update-checker/vendor/PucReadmeParser.php +++ /dev/null @@ -1,352 +0,0 @@ -parse_readme_contents( $file_contents ); - } - - function parse_readme_contents( $file_contents ) { - $file_contents = str_replace(array("\r\n", "\r"), "\n", $file_contents); - $file_contents = trim($file_contents); - if ( 0 === strpos( $file_contents, "\xEF\xBB\xBF" ) ) - $file_contents = substr( $file_contents, 3 ); - - // Markdown transformations - $file_contents = preg_replace( "|^###([^#]+)#*?\s*?\n|im", '=$1='."\n", $file_contents ); - $file_contents = preg_replace( "|^##([^#]+)#*?\s*?\n|im", '==$1=='."\n", $file_contents ); - $file_contents = preg_replace( "|^#([^#]+)#*?\s*?\n|im", '===$1==='."\n", $file_contents ); - - // === Plugin Name === - // Must be the very first thing. - if ( !preg_match('|^===(.*)===|', $file_contents, $_name) ) - return array(); // require a name - $name = trim($_name[1], '='); - $name = $this->sanitize_text( $name ); - - $file_contents = $this->chop_string( $file_contents, $_name[0] ); - - - // Requires at least: 1.5 - if ( preg_match('|Requires at least:(.*)|i', $file_contents, $_requires_at_least) ) - $requires_at_least = $this->sanitize_text($_requires_at_least[1]); - else - $requires_at_least = NULL; - - - // Tested up to: 2.1 - if ( preg_match('|Tested up to:(.*)|i', $file_contents, $_tested_up_to) ) - $tested_up_to = $this->sanitize_text( $_tested_up_to[1] ); - else - $tested_up_to = NULL; - - // Requires PHP: 5.2.4 - if ( preg_match('|Requires PHP:(.*)|i', $file_contents, $_requires_php) ) { - $requires_php = $this->sanitize_text( $_requires_php[1] ); - } else { - $requires_php = null; - } - - // Stable tag: 10.4-ride-the-fire-eagle-danger-day - if ( preg_match('|Stable tag:(.*)|i', $file_contents, $_stable_tag) ) - $stable_tag = $this->sanitize_text( $_stable_tag[1] ); - else - $stable_tag = NULL; // we assume trunk, but don't set it here to tell the difference between specified trunk and default trunk - - - // Tags: some tag, another tag, we like tags - if ( preg_match('|Tags:(.*)|i', $file_contents, $_tags) ) { - $tags = preg_split('|,[\s]*?|', trim($_tags[1])); - foreach ( array_keys($tags) as $t ) - $tags[$t] = $this->sanitize_text( $tags[$t] ); - } else { - $tags = array(); - } - - - // Contributors: markjaquith, mdawaffe, zefrank - $contributors = array(); - if ( preg_match('|Contributors:(.*)|i', $file_contents, $_contributors) ) { - $temp_contributors = preg_split('|,[\s]*|', trim($_contributors[1])); - foreach ( array_keys($temp_contributors) as $c ) { - $tmp_sanitized = $this->user_sanitize( $temp_contributors[$c] ); - if ( strlen(trim($tmp_sanitized)) > 0 ) - $contributors[$c] = $tmp_sanitized; - unset($tmp_sanitized); - } - } - - - // Donate Link: URL - if ( preg_match('|Donate link:(.*)|i', $file_contents, $_donate_link) ) - $donate_link = esc_url( $_donate_link[1] ); - else - $donate_link = NULL; - - - // togs, conts, etc are optional and order shouldn't matter. So we chop them only after we've grabbed their values. - foreach ( array('tags', 'contributors', 'requires_at_least', 'tested_up_to', 'stable_tag', 'donate_link') as $chop ) { - if ( $$chop ) { - $_chop = '_' . $chop; - $file_contents = $this->chop_string( $file_contents, ${$_chop}[0] ); - } - } - - $file_contents = trim($file_contents); - - - // short-description fu - if ( !preg_match('/(^(.*?))^[\s]*=+?[\s]*.+?[\s]*=+?/ms', $file_contents, $_short_description) ) - $_short_description = array( 1 => &$file_contents, 2 => &$file_contents ); - $short_desc_filtered = $this->sanitize_text( $_short_description[2] ); - $short_desc_length = strlen($short_desc_filtered); - $short_description = substr($short_desc_filtered, 0, 150); - if ( $short_desc_length > strlen($short_description) ) - $truncated = true; - else - $truncated = false; - if ( $_short_description[1] ) - $file_contents = $this->chop_string( $file_contents, $_short_description[1] ); // yes, the [1] is intentional - - // == Section == - // Break into sections - // $_sections[0] will be the title of the first section, $_sections[1] will be the content of the first section - // the array alternates from there: title2, content2, title3, content3... and so forth - $_sections = preg_split('/^[\s]*==[\s]*(.+?)[\s]*==/m', $file_contents, -1, PREG_SPLIT_DELIM_CAPTURE|PREG_SPLIT_NO_EMPTY); - - $sections = array(); - for ( $i=0; $i < count($_sections); $i +=2 ) { - $title = $this->sanitize_text( $_sections[$i] ); - if ( isset($_sections[$i+1]) ) { - $content = preg_replace('/(^[\s]*)=[\s]+(.+?)[\s]+=/m', '$1

$2

', $_sections[$i+1]); - $content = $this->filter_text( $content, true ); - } else { - $content = ''; - } - $sections[str_replace(' ', '_', strtolower($title))] = array('title' => $title, 'content' => $content); - } - - - // Special sections - // This is where we nab our special sections, so we can enforce their order and treat them differently, if needed - // upgrade_notice is not a section, but parse it like it is for now - $final_sections = array(); - foreach ( array('description', 'installation', 'frequently_asked_questions', 'screenshots', 'changelog', 'change_log', 'upgrade_notice') as $special_section ) { - if ( isset($sections[$special_section]) ) { - $final_sections[$special_section] = $sections[$special_section]['content']; - unset($sections[$special_section]); - } - } - if ( isset($final_sections['change_log']) && empty($final_sections['changelog']) ) - $final_sections['changelog'] = $final_sections['change_log']; - - - $final_screenshots = array(); - if ( isset($final_sections['screenshots']) ) { - preg_match_all('|
  • (.*?)
  • |s', $final_sections['screenshots'], $screenshots, PREG_SET_ORDER); - if ( $screenshots ) { - foreach ( (array) $screenshots as $ss ) - $final_screenshots[] = $ss[1]; - } - } - - // Parse the upgrade_notice section specially: - // 1.0 => blah, 1.1 => fnord - $upgrade_notice = array(); - if ( isset($final_sections['upgrade_notice']) ) { - $split = preg_split( '#

    (.*?)

    #', $final_sections['upgrade_notice'], -1, PREG_SPLIT_DELIM_CAPTURE | PREG_SPLIT_NO_EMPTY ); - if ( count($split) >= 2 ) { - for ( $i = 0; $i < count( $split ); $i += 2 ) { - $upgrade_notice[$this->sanitize_text( $split[$i] )] = substr( $this->sanitize_text( $split[$i + 1] ), 0, 300 ); - } - } - unset( $final_sections['upgrade_notice'] ); - } - - // No description? - // No problem... we'll just fall back to the old style of description - // We'll even let you use markup this time! - $excerpt = false; - if ( !isset($final_sections['description']) ) { - $final_sections = array_merge(array('description' => $this->filter_text( $_short_description[2], true )), $final_sections); - $excerpt = true; - } - - - // dump the non-special sections into $remaining_content - // their order will be determined by their original order in the readme.txt - $remaining_content = ''; - foreach ( $sections as $s_name => $s_data ) { - $remaining_content .= "\n

    {$s_data['title']}

    \n{$s_data['content']}"; - } - $remaining_content = trim($remaining_content); - - - // All done! - // $r['tags'] and $r['contributors'] are simple arrays - // $r['sections'] is an array with named elements - $r = array( - 'name' => $name, - 'tags' => $tags, - 'requires_at_least' => $requires_at_least, - 'tested_up_to' => $tested_up_to, - 'requires_php' => $requires_php, - 'stable_tag' => $stable_tag, - 'contributors' => $contributors, - 'donate_link' => $donate_link, - 'short_description' => $short_description, - 'screenshots' => $final_screenshots, - 'is_excerpt' => $excerpt, - 'is_truncated' => $truncated, - 'sections' => $final_sections, - 'remaining_content' => $remaining_content, - 'upgrade_notice' => $upgrade_notice - ); - - return $r; - } - - function chop_string( $string, $chop ) { // chop a "prefix" from a string: Agressive! uses strstr not 0 === strpos - if ( $_string = strstr($string, $chop) ) { - $_string = substr($_string, strlen($chop)); - return trim($_string); - } else { - return trim($string); - } - } - - function user_sanitize( $text, $strict = false ) { // whitelisted chars - if ( function_exists('user_sanitize') ) // bbPress native - return user_sanitize( $text, $strict ); - - if ( $strict ) { - $text = preg_replace('/[^a-z0-9-]/i', '', $text); - $text = preg_replace('|-+|', '-', $text); - } else { - $text = preg_replace('/[^a-z0-9_-]/i', '', $text); - } - return $text; - } - - function sanitize_text( $text ) { // not fancy - $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; - } - - function filter_text( $text, $markdown = false ) { // fancy, Markdown - $text = trim($text); - - $text = call_user_func( array( __CLASS__, 'code_trick' ), $text, $markdown ); // A better parser than Markdown's for: backticks -> CODE - - if ( $markdown ) { // Parse markdown. - if ( !class_exists('Parsedown', false) ) { - /** @noinspection PhpIncludeInspection */ - require_once(dirname(__FILE__) . '/Parsedown' . (version_compare(PHP_VERSION, '5.3.0', '>=') ? '' : 'Legacy') . '.php'); - } - $instance = Parsedown::instance(); - $text = $instance->text($text); - } - - $allowed = array( - 'a' => array( - 'href' => array(), - 'title' => array(), - 'rel' => array()), - 'blockquote' => array('cite' => array()), - 'br' => array(), - 'p' => array(), - 'code' => array(), - 'pre' => array(), - 'em' => array(), - 'strong' => array(), - 'ul' => array(), - 'ol' => array(), - 'li' => array(), - 'h3' => array(), - 'h4' => array() - ); - - $text = balanceTags($text); - - $text = wp_kses( $text, $allowed ); - $text = trim($text); - return $text; - } - - function code_trick( $text, $markdown ) { // Don't use bbPress native function - it's incompatible with Markdown - // If doing markdown, first take any user formatted code blocks and turn them into backticks so that - // markdown will preserve things like underscores in code blocks - if ( $markdown ) - $text = preg_replace_callback("!(
    |)(.*?)(
    |)!s", array( __CLASS__,'decodeit'), $text); - - $text = str_replace(array("\r\n", "\r"), "\n", $text); - if ( !$markdown ) { - // This gets the "inline" code blocks, but can't be used with Markdown. - $text = preg_replace_callback("|(`)(.*?)`|", array( __CLASS__, 'encodeit'), $text); - // This gets the "block level" code blocks and converts them to PRE CODE - $text = preg_replace_callback("!(^|\n)`(.*?)`!s", array( __CLASS__, 'encodeit'), $text); - } else { - // Markdown can do inline code, we convert bbPress style block level code to Markdown style - $text = preg_replace_callback("!(^|\n)([ \t]*?)`(.*?)`!s", array( __CLASS__, 'indent'), $text); - } - return $text; - } - - function indent( $matches ) { - $text = $matches[3]; - $text = preg_replace('|^|m', $matches[2] . ' ', $text); - return $matches[1] . $text; - } - - function encodeit( $matches ) { - if ( function_exists('encodeit') ) // bbPress native - return encodeit( $matches ); - - $text = trim($matches[2]); - $text = htmlspecialchars($text, ENT_QUOTES); - $text = str_replace(array("\r\n", "\r"), "\n", $text); - $text = preg_replace("|\n\n\n+|", "\n\n", $text); - $text = str_replace('&lt;', '<', $text); - $text = str_replace('&gt;', '>', $text); - $text = "$text"; - if ( "`" != $matches[1] ) - $text = "
    $text
    "; - return $text; - } - - function decodeit( $matches ) { - if ( function_exists('decodeit') ) // bbPress native - return decodeit( $matches ); - - $text = $matches[2]; - $trans_table = array_flip(get_html_translation_table(HTML_ENTITIES)); - $text = strtr($text, $trans_table); - $text = str_replace('
    ', '', $text); - $text = str_replace('&', '&', $text); - $text = str_replace(''', "'", $text); - if ( '
    ' == $matches[1] )
    -			$text = "\n$text\n";
    -		return "`$text`";
    -	}
    -
    -} // end class
    -
    -endif;