├── CHANGES.md ├── vendor ├── composer │ ├── autoload_namespaces.php │ ├── autoload_classmap.php │ ├── autoload_files.php │ ├── autoload_psr4.php │ ├── platform_check.php │ ├── LICENSE │ ├── autoload_static.php │ ├── autoload_real.php │ ├── installed.php │ ├── installed.json │ ├── InstalledVersions.php │ └── ClassLoader.php ├── afragen │ └── add-plugin-dependency-api │ │ ├── composer.json │ │ ├── LICENSE │ │ ├── README.md │ │ └── add-plugin-dependency-api.php └── autoload.php ├── README.md ├── composer.json ├── readme.txt ├── plugin.php └── LICENSE /CHANGES.md: -------------------------------------------------------------------------------- 1 | [unreleased] 2 | * initial commit 3 | -------------------------------------------------------------------------------- /vendor/composer/autoload_namespaces.php: -------------------------------------------------------------------------------- 1 | $vendorDir . '/composer/InstalledVersions.php', 10 | ); 11 | -------------------------------------------------------------------------------- /vendor/composer/autoload_files.php: -------------------------------------------------------------------------------- 1 | $vendorDir . '/afragen/add-plugin-dependency-api/add-plugin-dependency-api.php', 10 | ); 11 | -------------------------------------------------------------------------------- /vendor/composer/autoload_psr4.php: -------------------------------------------------------------------------------- 1 | array($vendorDir . '/dealerdirect/phpcodesniffer-composer-installer/src'), 10 | ); 11 | -------------------------------------------------------------------------------- /vendor/afragen/add-plugin-dependency-api/composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "afragen/add-plugin-dependency-api", 3 | "description": "Library that helps WordPress plugin dependency management.", 4 | "version": "0.4.8", 5 | "type": "library", 6 | "license": "MIT", 7 | "authors": [ 8 | { 9 | "name": "Andy Fragen", 10 | "email": "andy@thefragens.com", 11 | "homepage": "https://thefragens.com", 12 | "role": "Developer" 13 | } 14 | ], 15 | "prefer-stable": true, 16 | "require": { 17 | "php": ">=5.6" 18 | }, 19 | "support": { 20 | "issues": "https://github.com/afragen/add-plugin-dependency-api/issues", 21 | "source": "https://github.com/afragen/add-plugin-dependency-api" 22 | }, 23 | "autoload": { 24 | "files": [ 25 | "add-plugin-dependency-api.php" 26 | ] 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /vendor/autoload.php: -------------------------------------------------------------------------------- 1 | 9 | * License: MIT 10 | 11 | This plugin provides for the Git Updater plugin to be used as a plugin dependency. 12 | 13 | ## Description 14 | 15 | This plugin, when added to the dot org plugin repository, can be used to load the plugin card for Git Updater in the Dependencies tab of the Add Plugin page. This enables a one-click install of the Git Updater plugin. 16 | 17 | This dependency loader plugin **must** be in the official WP Plugin Repository to function. 18 | 19 | The Plugin Dependencies feature plugin must be installed for this function, until it is merged with core. 20 | 21 | If your plugin requires Git Updater for updating you can install the following headers in your main plugin file. 22 | 23 | `Requires Plugins: git-updater, git-updater-dependency-loader` 24 | -------------------------------------------------------------------------------- /vendor/composer/platform_check.php: -------------------------------------------------------------------------------- 1 | = 70200)) { 8 | $issues[] = 'Your Composer dependencies require a PHP version ">= 7.2.0". You are running ' . PHP_VERSION . '.'; 9 | } 10 | 11 | if ($issues) { 12 | if (!headers_sent()) { 13 | header('HTTP/1.1 500 Internal Server Error'); 14 | } 15 | if (!ini_get('display_errors')) { 16 | if (PHP_SAPI === 'cli' || PHP_SAPI === 'phpdbg') { 17 | fwrite(STDERR, 'Composer detected issues in your platform:' . PHP_EOL.PHP_EOL . implode(PHP_EOL, $issues) . PHP_EOL.PHP_EOL); 18 | } elseif (!headers_sent()) { 19 | echo 'Composer detected issues in your platform:' . PHP_EOL.PHP_EOL . str_replace('You are running '.PHP_VERSION.'.', '', implode(PHP_EOL, $issues)) . PHP_EOL.PHP_EOL; 20 | } 21 | } 22 | trigger_error( 23 | 'Composer detected issues in your platform: ' . implode(' ', $issues), 24 | E_USER_ERROR 25 | ); 26 | } 27 | -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "afragen/git-updater-dependency-loader", 3 | "description": "Add plugin card data for non-dot org dependencies, Git Updater", 4 | "type": "wordpress-plugin", 5 | "license": "MIT", 6 | "authors": [ 7 | { 8 | "name": "Andy Fragen", 9 | "email": "andy@thefragens.com", 10 | "homepage": "https://thefragens.com", 11 | "role": "Developer" 12 | } 13 | ], 14 | "support": { 15 | "issues": "https://github.com/afragen/git-updater-dependency-loader/issues", 16 | "source": "https://github.com/afragen/git-updater-dependency-loader" 17 | }, 18 | "prefer-stable": true, 19 | "require": { 20 | "php": ">=7.2", 21 | "afragen/add-plugin-dependency-api": "^0" 22 | }, 23 | "require-dev": { 24 | "dealerdirect/phpcodesniffer-composer-installer": "^0.7.0", 25 | "squizlabs/php_codesniffer": "3.6.0", 26 | "wp-coding-standards/wpcs": "~2.3.0" 27 | }, 28 | "config": { 29 | "allow-plugins": { 30 | "dealerdirect/phpcodesniffer-composer-installer": true 31 | } 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /readme.txt: -------------------------------------------------------------------------------- 1 | # Git Updater Dependency Loader 2 | 3 | * Contributors: afragen 4 | * Tags: git updater, plugin dependency 5 | * Requires at least: 5.9 6 | * Requires PHP: 7.2 7 | * Tested up to: 6.2 8 | * Stable tag: 0.1.0 9 | * Donate link: 10 | * License: MIT 11 | 12 | This plugin provides for the Git Updater plugin to be used as a plugin dependency. 13 | 14 | ## Description 15 | 16 | This plugin, when added to the dot org plugin repository, can be used to load the plugin card for Git Updater in the Dependencies tab of the Add Plugin page. This enables a one-click install of the Git Updater plugin. 17 | 18 | This dependency loader plugin **must** be in the official WP Plugin Repository to function. 19 | 20 | The Plugin Dependencies feature plugin must be installed for this function, until it is merged with core. 21 | 22 | If your plugin requires Git Updater for updating you can install the following headers in your main plugin file. 23 | 24 | `Requires Plugins: git-updater, git-updater-dependency-loader` 25 | 26 | ## Changelog 27 | [unreleased] 28 | -------------------------------------------------------------------------------- /plugin.php: -------------------------------------------------------------------------------- 1 | __DIR__ . '/..' . '/afragen/add-plugin-dependency-api/add-plugin-dependency-api.php', 11 | ); 12 | 13 | public static $prefixLengthsPsr4 = array ( 14 | 'D' => 15 | array ( 16 | 'Dealerdirect\\Composer\\Plugin\\Installers\\PHPCodeSniffer\\' => 55, 17 | ), 18 | ); 19 | 20 | public static $prefixDirsPsr4 = array ( 21 | 'Dealerdirect\\Composer\\Plugin\\Installers\\PHPCodeSniffer\\' => 22 | array ( 23 | 0 => __DIR__ . '/..' . '/dealerdirect/phpcodesniffer-composer-installer/src', 24 | ), 25 | ); 26 | 27 | public static $classMap = array ( 28 | 'Composer\\InstalledVersions' => __DIR__ . '/..' . '/composer/InstalledVersions.php', 29 | ); 30 | 31 | public static function getInitializer(ClassLoader $loader) 32 | { 33 | return \Closure::bind(function () use ($loader) { 34 | $loader->prefixLengthsPsr4 = ComposerStaticInitb3fdad6fd7ff328083c1b11ad5c92993::$prefixLengthsPsr4; 35 | $loader->prefixDirsPsr4 = ComposerStaticInitb3fdad6fd7ff328083c1b11ad5c92993::$prefixDirsPsr4; 36 | $loader->classMap = ComposerStaticInitb3fdad6fd7ff328083c1b11ad5c92993::$classMap; 37 | 38 | }, null, ClassLoader::class); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /vendor/composer/autoload_real.php: -------------------------------------------------------------------------------- 1 | register(true); 35 | 36 | $filesToLoad = \Composer\Autoload\ComposerStaticInitb3fdad6fd7ff328083c1b11ad5c92993::$files; 37 | $requireFile = \Closure::bind(static function ($fileIdentifier, $file) { 38 | if (empty($GLOBALS['__composer_autoload_files'][$fileIdentifier])) { 39 | $GLOBALS['__composer_autoload_files'][$fileIdentifier] = true; 40 | 41 | require $file; 42 | } 43 | }, null, null); 44 | foreach ($filesToLoad as $fileIdentifier => $file) { 45 | $requireFile($fileIdentifier, $file); 46 | } 47 | 48 | return $loader; 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /vendor/afragen/add-plugin-dependency-api/README.md: -------------------------------------------------------------------------------- 1 | # Add Plugin Dependency API 2 | 3 | * Contributors: [Andy Fragen](https://github.com/afragen), [contributors](https://github.com/afragen/add-plugin-dependency-api/graphs/contributors) 4 | * Tags: plugin dependency 5 | * Requires at least: 6.0 6 | * Requires PHP: 5.6 7 | * Stable tag: main 8 | * Donate link: 9 | * License: MIT 10 | 11 | Composer library for adding a plugin dependency response based upon use with Git Updater v12 or greater. 12 | 13 | ## Description 14 | 15 | This is an example to developers of non dot-org plugins that wish to take advantage of the Plugin Dependencies feature from the `Requires Plugins` header. 16 | 17 | You can use **composer** to install this package within your WordPress plugin / theme. 18 | 19 | **Please ensure you are using the latest version of this framework in your `composer.json`** 20 | 21 | 1. Within your plugin or theme root folder, run the following command: 22 | 23 | ```shell 24 | composer require afragen/add-plugin-dependency-api 25 | ``` 26 | 27 | 2. Add a filter to your plugin that requires a dependency that returns an array or JSON response containing a REST endpoint that returns a valid `plugins_api()` response. 28 | 29 | A query arg of the plugin slug, `?slug=my-plugin-dependency`, will be passed to the endpoint returned from the filter. The slug originates from the `Require Plugins` header. 30 | 31 | ```php 32 | // Add the sites with REST enpoints that return plugins_api() data when passed `slug` query arg. 33 | // You can also return URL to a JSON file containing the appropriate data. 34 | add_filter( 35 | 'plugin_dependency_endpoints', 36 | function () { 37 | return [ 'https://git-updater.com/wp-json/git-updater/v1/plugins-api/' ]; 38 | } 39 | ); 40 | ``` 41 | 42 | To see an example REST endpoint return view in the browser. 43 | 44 | ## Development 45 | 46 | PRs are welcome against the `develop` branch. 47 | -------------------------------------------------------------------------------- /vendor/composer/installed.php: -------------------------------------------------------------------------------- 1 | array( 3 | 'name' => 'afragen/git-updater-dependency-loader', 4 | 'pretty_version' => 'dev-main', 5 | 'version' => 'dev-main', 6 | 'reference' => 'd2704ea636ed607ab07bf74dae475ec729a31e4c', 7 | 'type' => 'wordpress-plugin', 8 | 'install_path' => __DIR__ . '/../../', 9 | 'aliases' => array(), 10 | 'dev' => true, 11 | ), 12 | 'versions' => array( 13 | 'afragen/add-plugin-dependency-api' => array( 14 | 'pretty_version' => '0.4.8', 15 | 'version' => '0.4.8.0', 16 | 'reference' => 'f88b8161528e7893a9de305077a52403a4c37e4d', 17 | 'type' => 'library', 18 | 'install_path' => __DIR__ . '/../afragen/add-plugin-dependency-api', 19 | 'aliases' => array(), 20 | 'dev_requirement' => false, 21 | ), 22 | 'afragen/git-updater-dependency-loader' => array( 23 | 'pretty_version' => 'dev-main', 24 | 'version' => 'dev-main', 25 | 'reference' => 'd2704ea636ed607ab07bf74dae475ec729a31e4c', 26 | 'type' => 'wordpress-plugin', 27 | 'install_path' => __DIR__ . '/../../', 28 | 'aliases' => array(), 29 | 'dev_requirement' => false, 30 | ), 31 | 'dealerdirect/phpcodesniffer-composer-installer' => array( 32 | 'pretty_version' => 'v0.7.2', 33 | 'version' => '0.7.2.0', 34 | 'reference' => '1c968e542d8843d7cd71de3c5c9c3ff3ad71a1db', 35 | 'type' => 'composer-plugin', 36 | 'install_path' => __DIR__ . '/../dealerdirect/phpcodesniffer-composer-installer', 37 | 'aliases' => array(), 38 | 'dev_requirement' => true, 39 | ), 40 | 'squizlabs/php_codesniffer' => array( 41 | 'pretty_version' => '3.6.0', 42 | 'version' => '3.6.0.0', 43 | 'reference' => 'ffced0d2c8fa8e6cdc4d695a743271fab6c38625', 44 | 'type' => 'library', 45 | 'install_path' => __DIR__ . '/../squizlabs/php_codesniffer', 46 | 'aliases' => array(), 47 | 'dev_requirement' => true, 48 | ), 49 | 'wp-coding-standards/wpcs' => array( 50 | 'pretty_version' => '2.3.0', 51 | 'version' => '2.3.0.0', 52 | 'reference' => '7da1894633f168fe244afc6de00d141f27517b62', 53 | 'type' => 'phpcodesniffer-standard', 54 | 'install_path' => __DIR__ . '/../wp-coding-standards/wpcs', 55 | 'aliases' => array(), 56 | 'dev_requirement' => true, 57 | ), 58 | ), 59 | ); 60 | -------------------------------------------------------------------------------- /vendor/afragen/add-plugin-dependency-api/add-plugin-dependency-api.php: -------------------------------------------------------------------------------- 1 | slug ) 58 | ) { 59 | continue; 60 | } 61 | 62 | $url = add_query_arg( 'slug', $args->slug, untrailingslashit( $endpoint ) ); 63 | $response = wp_remote_get( $url ); 64 | 65 | // Convert response to associative array. 66 | $response = json_decode( wp_remote_retrieve_body( $response ), true ); 67 | if ( null === $response || isset( $response['error'] ) || isset( $response['code'] ) ) { 68 | $message = isset( $response['error'] ) ? $response['error'] : ''; 69 | $response = new WP_Error( 'error', 'Error retrieving plugin data.', $message ); 70 | } 71 | if ( ! is_wp_error( $response ) ) { 72 | break; 73 | } 74 | } 75 | 76 | // Add slug to hook_extra. 77 | add_filter( 78 | 'upgrader_package_options', 79 | function ( $options ) use ( $args ) { 80 | $options['hook_extra']['slug'] = $args->slug; 81 | 82 | return $options; 83 | }, 84 | 10, 85 | 1 86 | ); 87 | } 88 | 89 | return (object) $response; 90 | } 91 | 92 | /** 93 | * Filter `upgrader_post_install` for plugin dependencies. 94 | * 95 | * For correct renaming of downloaded plugin directory, 96 | * some downloads may not be formatted correctly. 97 | * 98 | * @param bool $true Default is true. 99 | * @param array $hook_extra Array of data from hook. 100 | * @param array $result Array of data for installation. 101 | * 102 | * @return bool 103 | */ 104 | public function upgrader_post_install( $true, $hook_extra, $result ) { 105 | global $wp_filesystem; 106 | 107 | if ( ! isset( $hook_extra['slug'] ) ) { 108 | return $true; 109 | } 110 | 111 | $from = untrailingslashit( $result['destination'] ); 112 | $to = trailingslashit( $result['local_destination'] ) . $hook_extra['slug']; 113 | 114 | if ( trailingslashit( strtolower( $from ) ) !== trailingslashit( strtolower( $to ) ) ) { 115 | if ( function_exists( 'move_dir' ) ) { 116 | $true = move_dir( $from, $to, true ); 117 | } elseif ( ! rename( $from, $to ) ) { 118 | $wp_filesystem->mkdir( $to ); 119 | $true = copy_dir( $from, $to, [ basename( $to ) ] ); 120 | $wp_filesystem->delete( $from, true ); 121 | } 122 | } 123 | 124 | return $true; 125 | } 126 | } 127 | } 128 | 129 | ( new Plugin_Dependency_API() )->load_hooks(); 130 | -------------------------------------------------------------------------------- /vendor/composer/installed.json: -------------------------------------------------------------------------------- 1 | { 2 | "packages": [ 3 | { 4 | "name": "afragen/add-plugin-dependency-api", 5 | "version": "0.4.8", 6 | "version_normalized": "0.4.8.0", 7 | "source": { 8 | "type": "git", 9 | "url": "https://github.com/afragen/add-plugin-dependency-api.git", 10 | "reference": "f88b8161528e7893a9de305077a52403a4c37e4d" 11 | }, 12 | "dist": { 13 | "type": "zip", 14 | "url": "https://api.github.com/repos/afragen/add-plugin-dependency-api/zipball/f88b8161528e7893a9de305077a52403a4c37e4d", 15 | "reference": "f88b8161528e7893a9de305077a52403a4c37e4d", 16 | "shasum": "" 17 | }, 18 | "require": { 19 | "php": ">=5.6" 20 | }, 21 | "time": "2023-03-18T20:03:48+00:00", 22 | "type": "library", 23 | "installation-source": "dist", 24 | "autoload": { 25 | "files": [ 26 | "add-plugin-dependency-api.php" 27 | ] 28 | }, 29 | "notification-url": "https://packagist.org/downloads/", 30 | "license": [ 31 | "MIT" 32 | ], 33 | "authors": [ 34 | { 35 | "name": "Andy Fragen", 36 | "email": "andy@thefragens.com", 37 | "homepage": "https://thefragens.com", 38 | "role": "Developer" 39 | } 40 | ], 41 | "description": "Library that helps WordPress plugin dependency management.", 42 | "support": { 43 | "issues": "https://github.com/afragen/add-plugin-dependency-api/issues", 44 | "source": "https://github.com/afragen/add-plugin-dependency-api" 45 | }, 46 | "funding": [ 47 | { 48 | "url": "https://github.com/afragen", 49 | "type": "github" 50 | } 51 | ], 52 | "install-path": "../afragen/add-plugin-dependency-api" 53 | }, 54 | { 55 | "name": "dealerdirect/phpcodesniffer-composer-installer", 56 | "version": "v0.7.2", 57 | "version_normalized": "0.7.2.0", 58 | "source": { 59 | "type": "git", 60 | "url": "https://github.com/Dealerdirect/phpcodesniffer-composer-installer.git", 61 | "reference": "1c968e542d8843d7cd71de3c5c9c3ff3ad71a1db" 62 | }, 63 | "dist": { 64 | "type": "zip", 65 | "url": "https://api.github.com/repos/Dealerdirect/phpcodesniffer-composer-installer/zipball/1c968e542d8843d7cd71de3c5c9c3ff3ad71a1db", 66 | "reference": "1c968e542d8843d7cd71de3c5c9c3ff3ad71a1db", 67 | "shasum": "" 68 | }, 69 | "require": { 70 | "composer-plugin-api": "^1.0 || ^2.0", 71 | "php": ">=5.3", 72 | "squizlabs/php_codesniffer": "^2.0 || ^3.1.0 || ^4.0" 73 | }, 74 | "require-dev": { 75 | "composer/composer": "*", 76 | "php-parallel-lint/php-parallel-lint": "^1.3.1", 77 | "phpcompatibility/php-compatibility": "^9.0" 78 | }, 79 | "time": "2022-02-04T12:51:07+00:00", 80 | "type": "composer-plugin", 81 | "extra": { 82 | "class": "Dealerdirect\\Composer\\Plugin\\Installers\\PHPCodeSniffer\\Plugin" 83 | }, 84 | "installation-source": "dist", 85 | "autoload": { 86 | "psr-4": { 87 | "Dealerdirect\\Composer\\Plugin\\Installers\\PHPCodeSniffer\\": "src/" 88 | } 89 | }, 90 | "notification-url": "https://packagist.org/downloads/", 91 | "license": [ 92 | "MIT" 93 | ], 94 | "authors": [ 95 | { 96 | "name": "Franck Nijhof", 97 | "email": "franck.nijhof@dealerdirect.com", 98 | "homepage": "http://www.frenck.nl", 99 | "role": "Developer / IT Manager" 100 | }, 101 | { 102 | "name": "Contributors", 103 | "homepage": "https://github.com/Dealerdirect/phpcodesniffer-composer-installer/graphs/contributors" 104 | } 105 | ], 106 | "description": "PHP_CodeSniffer Standards Composer Installer Plugin", 107 | "homepage": "http://www.dealerdirect.com", 108 | "keywords": [ 109 | "PHPCodeSniffer", 110 | "PHP_CodeSniffer", 111 | "code quality", 112 | "codesniffer", 113 | "composer", 114 | "installer", 115 | "phpcbf", 116 | "phpcs", 117 | "plugin", 118 | "qa", 119 | "quality", 120 | "standard", 121 | "standards", 122 | "style guide", 123 | "stylecheck", 124 | "tests" 125 | ], 126 | "support": { 127 | "issues": "https://github.com/dealerdirect/phpcodesniffer-composer-installer/issues", 128 | "source": "https://github.com/dealerdirect/phpcodesniffer-composer-installer" 129 | }, 130 | "install-path": "../dealerdirect/phpcodesniffer-composer-installer" 131 | }, 132 | { 133 | "name": "squizlabs/php_codesniffer", 134 | "version": "3.6.0", 135 | "version_normalized": "3.6.0.0", 136 | "source": { 137 | "type": "git", 138 | "url": "https://github.com/squizlabs/PHP_CodeSniffer.git", 139 | "reference": "ffced0d2c8fa8e6cdc4d695a743271fab6c38625" 140 | }, 141 | "dist": { 142 | "type": "zip", 143 | "url": "https://api.github.com/repos/squizlabs/PHP_CodeSniffer/zipball/ffced0d2c8fa8e6cdc4d695a743271fab6c38625", 144 | "reference": "ffced0d2c8fa8e6cdc4d695a743271fab6c38625", 145 | "shasum": "" 146 | }, 147 | "require": { 148 | "ext-simplexml": "*", 149 | "ext-tokenizer": "*", 150 | "ext-xmlwriter": "*", 151 | "php": ">=5.4.0" 152 | }, 153 | "require-dev": { 154 | "phpunit/phpunit": "^4.0 || ^5.0 || ^6.0 || ^7.0" 155 | }, 156 | "time": "2021-04-09T00:54:41+00:00", 157 | "bin": [ 158 | "bin/phpcs", 159 | "bin/phpcbf" 160 | ], 161 | "type": "library", 162 | "extra": { 163 | "branch-alias": { 164 | "dev-master": "3.x-dev" 165 | } 166 | }, 167 | "installation-source": "dist", 168 | "notification-url": "https://packagist.org/downloads/", 169 | "license": [ 170 | "BSD-3-Clause" 171 | ], 172 | "authors": [ 173 | { 174 | "name": "Greg Sherwood", 175 | "role": "lead" 176 | } 177 | ], 178 | "description": "PHP_CodeSniffer tokenizes PHP, JavaScript and CSS files and detects violations of a defined set of coding standards.", 179 | "homepage": "https://github.com/squizlabs/PHP_CodeSniffer", 180 | "keywords": [ 181 | "phpcs", 182 | "standards" 183 | ], 184 | "support": { 185 | "issues": "https://github.com/squizlabs/PHP_CodeSniffer/issues", 186 | "source": "https://github.com/squizlabs/PHP_CodeSniffer", 187 | "wiki": "https://github.com/squizlabs/PHP_CodeSniffer/wiki" 188 | }, 189 | "install-path": "../squizlabs/php_codesniffer" 190 | }, 191 | { 192 | "name": "wp-coding-standards/wpcs", 193 | "version": "2.3.0", 194 | "version_normalized": "2.3.0.0", 195 | "source": { 196 | "type": "git", 197 | "url": "https://github.com/WordPress/WordPress-Coding-Standards.git", 198 | "reference": "7da1894633f168fe244afc6de00d141f27517b62" 199 | }, 200 | "dist": { 201 | "type": "zip", 202 | "url": "https://api.github.com/repos/WordPress/WordPress-Coding-Standards/zipball/7da1894633f168fe244afc6de00d141f27517b62", 203 | "reference": "7da1894633f168fe244afc6de00d141f27517b62", 204 | "shasum": "" 205 | }, 206 | "require": { 207 | "php": ">=5.4", 208 | "squizlabs/php_codesniffer": "^3.3.1" 209 | }, 210 | "require-dev": { 211 | "dealerdirect/phpcodesniffer-composer-installer": "^0.5 || ^0.6", 212 | "phpcompatibility/php-compatibility": "^9.0", 213 | "phpcsstandards/phpcsdevtools": "^1.0", 214 | "phpunit/phpunit": "^4.0 || ^5.0 || ^6.0 || ^7.0" 215 | }, 216 | "suggest": { 217 | "dealerdirect/phpcodesniffer-composer-installer": "^0.6 || This Composer plugin will sort out the PHPCS 'installed_paths' automatically." 218 | }, 219 | "time": "2020-05-13T23:57:56+00:00", 220 | "type": "phpcodesniffer-standard", 221 | "installation-source": "dist", 222 | "notification-url": "https://packagist.org/downloads/", 223 | "license": [ 224 | "MIT" 225 | ], 226 | "authors": [ 227 | { 228 | "name": "Contributors", 229 | "homepage": "https://github.com/WordPress/WordPress-Coding-Standards/graphs/contributors" 230 | } 231 | ], 232 | "description": "PHP_CodeSniffer rules (sniffs) to enforce WordPress coding conventions", 233 | "keywords": [ 234 | "phpcs", 235 | "standards", 236 | "wordpress" 237 | ], 238 | "support": { 239 | "issues": "https://github.com/WordPress/WordPress-Coding-Standards/issues", 240 | "source": "https://github.com/WordPress/WordPress-Coding-Standards", 241 | "wiki": "https://github.com/WordPress/WordPress-Coding-Standards/wiki" 242 | }, 243 | "install-path": "../wp-coding-standards/wpcs" 244 | } 245 | ], 246 | "dev": true, 247 | "dev-package-names": [ 248 | "dealerdirect/phpcodesniffer-composer-installer", 249 | "squizlabs/php_codesniffer", 250 | "wp-coding-standards/wpcs" 251 | ] 252 | } 253 | -------------------------------------------------------------------------------- /vendor/composer/InstalledVersions.php: -------------------------------------------------------------------------------- 1 | 7 | * Jordi Boggiano 8 | * 9 | * For the full copyright and license information, please view the LICENSE 10 | * file that was distributed with this source code. 11 | */ 12 | 13 | namespace Composer; 14 | 15 | use Composer\Autoload\ClassLoader; 16 | use Composer\Semver\VersionParser; 17 | 18 | /** 19 | * This class is copied in every Composer installed project and available to all 20 | * 21 | * See also https://getcomposer.org/doc/07-runtime.md#installed-versions 22 | * 23 | * To require its presence, you can require `composer-runtime-api ^2.0` 24 | * 25 | * @final 26 | */ 27 | class InstalledVersions 28 | { 29 | /** 30 | * @var mixed[]|null 31 | * @psalm-var array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array}|array{}|null 32 | */ 33 | private static $installed; 34 | 35 | /** 36 | * @var bool|null 37 | */ 38 | private static $canGetVendors; 39 | 40 | /** 41 | * @var array[] 42 | * @psalm-var array}> 43 | */ 44 | private static $installedByVendor = array(); 45 | 46 | /** 47 | * Returns a list of all package names which are present, either by being installed, replaced or provided 48 | * 49 | * @return string[] 50 | * @psalm-return list 51 | */ 52 | public static function getInstalledPackages() 53 | { 54 | $packages = array(); 55 | foreach (self::getInstalled() as $installed) { 56 | $packages[] = array_keys($installed['versions']); 57 | } 58 | 59 | if (1 === \count($packages)) { 60 | return $packages[0]; 61 | } 62 | 63 | return array_keys(array_flip(\call_user_func_array('array_merge', $packages))); 64 | } 65 | 66 | /** 67 | * Returns a list of all package names with a specific type e.g. 'library' 68 | * 69 | * @param string $type 70 | * @return string[] 71 | * @psalm-return list 72 | */ 73 | public static function getInstalledPackagesByType($type) 74 | { 75 | $packagesByType = array(); 76 | 77 | foreach (self::getInstalled() as $installed) { 78 | foreach ($installed['versions'] as $name => $package) { 79 | if (isset($package['type']) && $package['type'] === $type) { 80 | $packagesByType[] = $name; 81 | } 82 | } 83 | } 84 | 85 | return $packagesByType; 86 | } 87 | 88 | /** 89 | * Checks whether the given package is installed 90 | * 91 | * This also returns true if the package name is provided or replaced by another package 92 | * 93 | * @param string $packageName 94 | * @param bool $includeDevRequirements 95 | * @return bool 96 | */ 97 | public static function isInstalled($packageName, $includeDevRequirements = true) 98 | { 99 | foreach (self::getInstalled() as $installed) { 100 | if (isset($installed['versions'][$packageName])) { 101 | return $includeDevRequirements || !isset($installed['versions'][$packageName]['dev_requirement']) || $installed['versions'][$packageName]['dev_requirement'] === false; 102 | } 103 | } 104 | 105 | return false; 106 | } 107 | 108 | /** 109 | * Checks whether the given package satisfies a version constraint 110 | * 111 | * e.g. If you want to know whether version 2.3+ of package foo/bar is installed, you would call: 112 | * 113 | * Composer\InstalledVersions::satisfies(new VersionParser, 'foo/bar', '^2.3') 114 | * 115 | * @param VersionParser $parser Install composer/semver to have access to this class and functionality 116 | * @param string $packageName 117 | * @param string|null $constraint A version constraint to check for, if you pass one you have to make sure composer/semver is required by your package 118 | * @return bool 119 | */ 120 | public static function satisfies(VersionParser $parser, $packageName, $constraint) 121 | { 122 | $constraint = $parser->parseConstraints((string) $constraint); 123 | $provided = $parser->parseConstraints(self::getVersionRanges($packageName)); 124 | 125 | return $provided->matches($constraint); 126 | } 127 | 128 | /** 129 | * Returns a version constraint representing all the range(s) which are installed for a given package 130 | * 131 | * It is easier to use this via isInstalled() with the $constraint argument if you need to check 132 | * whether a given version of a package is installed, and not just whether it exists 133 | * 134 | * @param string $packageName 135 | * @return string Version constraint usable with composer/semver 136 | */ 137 | public static function getVersionRanges($packageName) 138 | { 139 | foreach (self::getInstalled() as $installed) { 140 | if (!isset($installed['versions'][$packageName])) { 141 | continue; 142 | } 143 | 144 | $ranges = array(); 145 | if (isset($installed['versions'][$packageName]['pretty_version'])) { 146 | $ranges[] = $installed['versions'][$packageName]['pretty_version']; 147 | } 148 | if (array_key_exists('aliases', $installed['versions'][$packageName])) { 149 | $ranges = array_merge($ranges, $installed['versions'][$packageName]['aliases']); 150 | } 151 | if (array_key_exists('replaced', $installed['versions'][$packageName])) { 152 | $ranges = array_merge($ranges, $installed['versions'][$packageName]['replaced']); 153 | } 154 | if (array_key_exists('provided', $installed['versions'][$packageName])) { 155 | $ranges = array_merge($ranges, $installed['versions'][$packageName]['provided']); 156 | } 157 | 158 | return implode(' || ', $ranges); 159 | } 160 | 161 | throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed'); 162 | } 163 | 164 | /** 165 | * @param string $packageName 166 | * @return string|null If the package is being replaced or provided but is not really installed, null will be returned as version, use satisfies or getVersionRanges if you need to know if a given version is present 167 | */ 168 | public static function getVersion($packageName) 169 | { 170 | foreach (self::getInstalled() as $installed) { 171 | if (!isset($installed['versions'][$packageName])) { 172 | continue; 173 | } 174 | 175 | if (!isset($installed['versions'][$packageName]['version'])) { 176 | return null; 177 | } 178 | 179 | return $installed['versions'][$packageName]['version']; 180 | } 181 | 182 | throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed'); 183 | } 184 | 185 | /** 186 | * @param string $packageName 187 | * @return string|null If the package is being replaced or provided but is not really installed, null will be returned as version, use satisfies or getVersionRanges if you need to know if a given version is present 188 | */ 189 | public static function getPrettyVersion($packageName) 190 | { 191 | foreach (self::getInstalled() as $installed) { 192 | if (!isset($installed['versions'][$packageName])) { 193 | continue; 194 | } 195 | 196 | if (!isset($installed['versions'][$packageName]['pretty_version'])) { 197 | return null; 198 | } 199 | 200 | return $installed['versions'][$packageName]['pretty_version']; 201 | } 202 | 203 | throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed'); 204 | } 205 | 206 | /** 207 | * @param string $packageName 208 | * @return string|null If the package is being replaced or provided but is not really installed, null will be returned as reference 209 | */ 210 | public static function getReference($packageName) 211 | { 212 | foreach (self::getInstalled() as $installed) { 213 | if (!isset($installed['versions'][$packageName])) { 214 | continue; 215 | } 216 | 217 | if (!isset($installed['versions'][$packageName]['reference'])) { 218 | return null; 219 | } 220 | 221 | return $installed['versions'][$packageName]['reference']; 222 | } 223 | 224 | throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed'); 225 | } 226 | 227 | /** 228 | * @param string $packageName 229 | * @return string|null If the package is being replaced or provided but is not really installed, null will be returned as install path. Packages of type metapackages also have a null install path. 230 | */ 231 | public static function getInstallPath($packageName) 232 | { 233 | foreach (self::getInstalled() as $installed) { 234 | if (!isset($installed['versions'][$packageName])) { 235 | continue; 236 | } 237 | 238 | return isset($installed['versions'][$packageName]['install_path']) ? $installed['versions'][$packageName]['install_path'] : null; 239 | } 240 | 241 | throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed'); 242 | } 243 | 244 | /** 245 | * @return array 246 | * @psalm-return array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool} 247 | */ 248 | public static function getRootPackage() 249 | { 250 | $installed = self::getInstalled(); 251 | 252 | return $installed[0]['root']; 253 | } 254 | 255 | /** 256 | * Returns the raw installed.php data for custom implementations 257 | * 258 | * @deprecated Use getAllRawData() instead which returns all datasets for all autoloaders present in the process. getRawData only returns the first dataset loaded, which may not be what you expect. 259 | * @return array[] 260 | * @psalm-return array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array} 261 | */ 262 | public static function getRawData() 263 | { 264 | @trigger_error('getRawData only returns the first dataset loaded, which may not be what you expect. Use getAllRawData() instead which returns all datasets for all autoloaders present in the process.', E_USER_DEPRECATED); 265 | 266 | if (null === self::$installed) { 267 | // only require the installed.php file if this file is loaded from its dumped location, 268 | // and not from its source location in the composer/composer package, see https://github.com/composer/composer/issues/9937 269 | if (substr(__DIR__, -8, 1) !== 'C') { 270 | self::$installed = include __DIR__ . '/installed.php'; 271 | } else { 272 | self::$installed = array(); 273 | } 274 | } 275 | 276 | return self::$installed; 277 | } 278 | 279 | /** 280 | * Returns the raw data of all installed.php which are currently loaded for custom implementations 281 | * 282 | * @return array[] 283 | * @psalm-return list}> 284 | */ 285 | public static function getAllRawData() 286 | { 287 | return self::getInstalled(); 288 | } 289 | 290 | /** 291 | * Lets you reload the static array from another file 292 | * 293 | * This is only useful for complex integrations in which a project needs to use 294 | * this class but then also needs to execute another project's autoloader in process, 295 | * and wants to ensure both projects have access to their version of installed.php. 296 | * 297 | * A typical case would be PHPUnit, where it would need to make sure it reads all 298 | * the data it needs from this class, then call reload() with 299 | * `require $CWD/vendor/composer/installed.php` (or similar) as input to make sure 300 | * the project in which it runs can then also use this class safely, without 301 | * interference between PHPUnit's dependencies and the project's dependencies. 302 | * 303 | * @param array[] $data A vendor/composer/installed.php data set 304 | * @return void 305 | * 306 | * @psalm-param array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array} $data 307 | */ 308 | public static function reload($data) 309 | { 310 | self::$installed = $data; 311 | self::$installedByVendor = array(); 312 | } 313 | 314 | /** 315 | * @return array[] 316 | * @psalm-return list}> 317 | */ 318 | private static function getInstalled() 319 | { 320 | if (null === self::$canGetVendors) { 321 | self::$canGetVendors = method_exists('Composer\Autoload\ClassLoader', 'getRegisteredLoaders'); 322 | } 323 | 324 | $installed = array(); 325 | 326 | if (self::$canGetVendors) { 327 | foreach (ClassLoader::getRegisteredLoaders() as $vendorDir => $loader) { 328 | if (isset(self::$installedByVendor[$vendorDir])) { 329 | $installed[] = self::$installedByVendor[$vendorDir]; 330 | } elseif (is_file($vendorDir.'/composer/installed.php')) { 331 | /** @var array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array} $required */ 332 | $required = require $vendorDir.'/composer/installed.php'; 333 | $installed[] = self::$installedByVendor[$vendorDir] = $required; 334 | if (null === self::$installed && strtr($vendorDir.'/composer', '\\', '/') === strtr(__DIR__, '\\', '/')) { 335 | self::$installed = $installed[count($installed) - 1]; 336 | } 337 | } 338 | } 339 | } 340 | 341 | if (null === self::$installed) { 342 | // only require the installed.php file if this file is loaded from its dumped location, 343 | // and not from its source location in the composer/composer package, see https://github.com/composer/composer/issues/9937 344 | if (substr(__DIR__, -8, 1) !== 'C') { 345 | /** @var array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array} $required */ 346 | $required = require __DIR__ . '/installed.php'; 347 | self::$installed = $required; 348 | } else { 349 | self::$installed = array(); 350 | } 351 | } 352 | 353 | if (self::$installed !== array()) { 354 | $installed[] = self::$installed; 355 | } 356 | 357 | return $installed; 358 | } 359 | } 360 | -------------------------------------------------------------------------------- /vendor/composer/ClassLoader.php: -------------------------------------------------------------------------------- 1 | 7 | * Jordi Boggiano 8 | * 9 | * For the full copyright and license information, please view the LICENSE 10 | * file that was distributed with this source code. 11 | */ 12 | 13 | namespace Composer\Autoload; 14 | 15 | /** 16 | * ClassLoader implements a PSR-0, PSR-4 and classmap class loader. 17 | * 18 | * $loader = new \Composer\Autoload\ClassLoader(); 19 | * 20 | * // register classes with namespaces 21 | * $loader->add('Symfony\Component', __DIR__.'/component'); 22 | * $loader->add('Symfony', __DIR__.'/framework'); 23 | * 24 | * // activate the autoloader 25 | * $loader->register(); 26 | * 27 | * // to enable searching the include path (eg. for PEAR packages) 28 | * $loader->setUseIncludePath(true); 29 | * 30 | * In this example, if you try to use a class in the Symfony\Component 31 | * namespace or one of its children (Symfony\Component\Console for instance), 32 | * the autoloader will first look for the class under the component/ 33 | * directory, and it will then fallback to the framework/ directory if not 34 | * found before giving up. 35 | * 36 | * This class is loosely based on the Symfony UniversalClassLoader. 37 | * 38 | * @author Fabien Potencier 39 | * @author Jordi Boggiano 40 | * @see https://www.php-fig.org/psr/psr-0/ 41 | * @see https://www.php-fig.org/psr/psr-4/ 42 | */ 43 | class ClassLoader 44 | { 45 | /** @var \Closure(string):void */ 46 | private static $includeFile; 47 | 48 | /** @var ?string */ 49 | private $vendorDir; 50 | 51 | // PSR-4 52 | /** 53 | * @var array[] 54 | * @psalm-var array> 55 | */ 56 | private $prefixLengthsPsr4 = array(); 57 | /** 58 | * @var array[] 59 | * @psalm-var array> 60 | */ 61 | private $prefixDirsPsr4 = array(); 62 | /** 63 | * @var array[] 64 | * @psalm-var array 65 | */ 66 | private $fallbackDirsPsr4 = array(); 67 | 68 | // PSR-0 69 | /** 70 | * @var array[] 71 | * @psalm-var array> 72 | */ 73 | private $prefixesPsr0 = array(); 74 | /** 75 | * @var array[] 76 | * @psalm-var array 77 | */ 78 | private $fallbackDirsPsr0 = array(); 79 | 80 | /** @var bool */ 81 | private $useIncludePath = false; 82 | 83 | /** 84 | * @var string[] 85 | * @psalm-var array 86 | */ 87 | private $classMap = array(); 88 | 89 | /** @var bool */ 90 | private $classMapAuthoritative = false; 91 | 92 | /** 93 | * @var bool[] 94 | * @psalm-var array 95 | */ 96 | private $missingClasses = array(); 97 | 98 | /** @var ?string */ 99 | private $apcuPrefix; 100 | 101 | /** 102 | * @var self[] 103 | */ 104 | private static $registeredLoaders = array(); 105 | 106 | /** 107 | * @param ?string $vendorDir 108 | */ 109 | public function __construct($vendorDir = null) 110 | { 111 | $this->vendorDir = $vendorDir; 112 | self::initializeIncludeClosure(); 113 | } 114 | 115 | /** 116 | * @return string[] 117 | */ 118 | public function getPrefixes() 119 | { 120 | if (!empty($this->prefixesPsr0)) { 121 | return call_user_func_array('array_merge', array_values($this->prefixesPsr0)); 122 | } 123 | 124 | return array(); 125 | } 126 | 127 | /** 128 | * @return array[] 129 | * @psalm-return array> 130 | */ 131 | public function getPrefixesPsr4() 132 | { 133 | return $this->prefixDirsPsr4; 134 | } 135 | 136 | /** 137 | * @return array[] 138 | * @psalm-return array 139 | */ 140 | public function getFallbackDirs() 141 | { 142 | return $this->fallbackDirsPsr0; 143 | } 144 | 145 | /** 146 | * @return array[] 147 | * @psalm-return array 148 | */ 149 | public function getFallbackDirsPsr4() 150 | { 151 | return $this->fallbackDirsPsr4; 152 | } 153 | 154 | /** 155 | * @return string[] Array of classname => path 156 | * @psalm-return array 157 | */ 158 | public function getClassMap() 159 | { 160 | return $this->classMap; 161 | } 162 | 163 | /** 164 | * @param string[] $classMap Class to filename map 165 | * @psalm-param array $classMap 166 | * 167 | * @return void 168 | */ 169 | public function addClassMap(array $classMap) 170 | { 171 | if ($this->classMap) { 172 | $this->classMap = array_merge($this->classMap, $classMap); 173 | } else { 174 | $this->classMap = $classMap; 175 | } 176 | } 177 | 178 | /** 179 | * Registers a set of PSR-0 directories for a given prefix, either 180 | * appending or prepending to the ones previously set for this prefix. 181 | * 182 | * @param string $prefix The prefix 183 | * @param string[]|string $paths The PSR-0 root directories 184 | * @param bool $prepend Whether to prepend the directories 185 | * 186 | * @return void 187 | */ 188 | public function add($prefix, $paths, $prepend = false) 189 | { 190 | if (!$prefix) { 191 | if ($prepend) { 192 | $this->fallbackDirsPsr0 = array_merge( 193 | (array) $paths, 194 | $this->fallbackDirsPsr0 195 | ); 196 | } else { 197 | $this->fallbackDirsPsr0 = array_merge( 198 | $this->fallbackDirsPsr0, 199 | (array) $paths 200 | ); 201 | } 202 | 203 | return; 204 | } 205 | 206 | $first = $prefix[0]; 207 | if (!isset($this->prefixesPsr0[$first][$prefix])) { 208 | $this->prefixesPsr0[$first][$prefix] = (array) $paths; 209 | 210 | return; 211 | } 212 | if ($prepend) { 213 | $this->prefixesPsr0[$first][$prefix] = array_merge( 214 | (array) $paths, 215 | $this->prefixesPsr0[$first][$prefix] 216 | ); 217 | } else { 218 | $this->prefixesPsr0[$first][$prefix] = array_merge( 219 | $this->prefixesPsr0[$first][$prefix], 220 | (array) $paths 221 | ); 222 | } 223 | } 224 | 225 | /** 226 | * Registers a set of PSR-4 directories for a given namespace, either 227 | * appending or prepending to the ones previously set for this namespace. 228 | * 229 | * @param string $prefix The prefix/namespace, with trailing '\\' 230 | * @param string[]|string $paths The PSR-4 base directories 231 | * @param bool $prepend Whether to prepend the directories 232 | * 233 | * @throws \InvalidArgumentException 234 | * 235 | * @return void 236 | */ 237 | public function addPsr4($prefix, $paths, $prepend = false) 238 | { 239 | if (!$prefix) { 240 | // Register directories for the root namespace. 241 | if ($prepend) { 242 | $this->fallbackDirsPsr4 = array_merge( 243 | (array) $paths, 244 | $this->fallbackDirsPsr4 245 | ); 246 | } else { 247 | $this->fallbackDirsPsr4 = array_merge( 248 | $this->fallbackDirsPsr4, 249 | (array) $paths 250 | ); 251 | } 252 | } elseif (!isset($this->prefixDirsPsr4[$prefix])) { 253 | // Register directories for a new namespace. 254 | $length = strlen($prefix); 255 | if ('\\' !== $prefix[$length - 1]) { 256 | throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator."); 257 | } 258 | $this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length; 259 | $this->prefixDirsPsr4[$prefix] = (array) $paths; 260 | } elseif ($prepend) { 261 | // Prepend directories for an already registered namespace. 262 | $this->prefixDirsPsr4[$prefix] = array_merge( 263 | (array) $paths, 264 | $this->prefixDirsPsr4[$prefix] 265 | ); 266 | } else { 267 | // Append directories for an already registered namespace. 268 | $this->prefixDirsPsr4[$prefix] = array_merge( 269 | $this->prefixDirsPsr4[$prefix], 270 | (array) $paths 271 | ); 272 | } 273 | } 274 | 275 | /** 276 | * Registers a set of PSR-0 directories for a given prefix, 277 | * replacing any others previously set for this prefix. 278 | * 279 | * @param string $prefix The prefix 280 | * @param string[]|string $paths The PSR-0 base directories 281 | * 282 | * @return void 283 | */ 284 | public function set($prefix, $paths) 285 | { 286 | if (!$prefix) { 287 | $this->fallbackDirsPsr0 = (array) $paths; 288 | } else { 289 | $this->prefixesPsr0[$prefix[0]][$prefix] = (array) $paths; 290 | } 291 | } 292 | 293 | /** 294 | * Registers a set of PSR-4 directories for a given namespace, 295 | * replacing any others previously set for this namespace. 296 | * 297 | * @param string $prefix The prefix/namespace, with trailing '\\' 298 | * @param string[]|string $paths The PSR-4 base directories 299 | * 300 | * @throws \InvalidArgumentException 301 | * 302 | * @return void 303 | */ 304 | public function setPsr4($prefix, $paths) 305 | { 306 | if (!$prefix) { 307 | $this->fallbackDirsPsr4 = (array) $paths; 308 | } else { 309 | $length = strlen($prefix); 310 | if ('\\' !== $prefix[$length - 1]) { 311 | throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator."); 312 | } 313 | $this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length; 314 | $this->prefixDirsPsr4[$prefix] = (array) $paths; 315 | } 316 | } 317 | 318 | /** 319 | * Turns on searching the include path for class files. 320 | * 321 | * @param bool $useIncludePath 322 | * 323 | * @return void 324 | */ 325 | public function setUseIncludePath($useIncludePath) 326 | { 327 | $this->useIncludePath = $useIncludePath; 328 | } 329 | 330 | /** 331 | * Can be used to check if the autoloader uses the include path to check 332 | * for classes. 333 | * 334 | * @return bool 335 | */ 336 | public function getUseIncludePath() 337 | { 338 | return $this->useIncludePath; 339 | } 340 | 341 | /** 342 | * Turns off searching the prefix and fallback directories for classes 343 | * that have not been registered with the class map. 344 | * 345 | * @param bool $classMapAuthoritative 346 | * 347 | * @return void 348 | */ 349 | public function setClassMapAuthoritative($classMapAuthoritative) 350 | { 351 | $this->classMapAuthoritative = $classMapAuthoritative; 352 | } 353 | 354 | /** 355 | * Should class lookup fail if not found in the current class map? 356 | * 357 | * @return bool 358 | */ 359 | public function isClassMapAuthoritative() 360 | { 361 | return $this->classMapAuthoritative; 362 | } 363 | 364 | /** 365 | * APCu prefix to use to cache found/not-found classes, if the extension is enabled. 366 | * 367 | * @param string|null $apcuPrefix 368 | * 369 | * @return void 370 | */ 371 | public function setApcuPrefix($apcuPrefix) 372 | { 373 | $this->apcuPrefix = function_exists('apcu_fetch') && filter_var(ini_get('apc.enabled'), FILTER_VALIDATE_BOOLEAN) ? $apcuPrefix : null; 374 | } 375 | 376 | /** 377 | * The APCu prefix in use, or null if APCu caching is not enabled. 378 | * 379 | * @return string|null 380 | */ 381 | public function getApcuPrefix() 382 | { 383 | return $this->apcuPrefix; 384 | } 385 | 386 | /** 387 | * Registers this instance as an autoloader. 388 | * 389 | * @param bool $prepend Whether to prepend the autoloader or not 390 | * 391 | * @return void 392 | */ 393 | public function register($prepend = false) 394 | { 395 | spl_autoload_register(array($this, 'loadClass'), true, $prepend); 396 | 397 | if (null === $this->vendorDir) { 398 | return; 399 | } 400 | 401 | if ($prepend) { 402 | self::$registeredLoaders = array($this->vendorDir => $this) + self::$registeredLoaders; 403 | } else { 404 | unset(self::$registeredLoaders[$this->vendorDir]); 405 | self::$registeredLoaders[$this->vendorDir] = $this; 406 | } 407 | } 408 | 409 | /** 410 | * Unregisters this instance as an autoloader. 411 | * 412 | * @return void 413 | */ 414 | public function unregister() 415 | { 416 | spl_autoload_unregister(array($this, 'loadClass')); 417 | 418 | if (null !== $this->vendorDir) { 419 | unset(self::$registeredLoaders[$this->vendorDir]); 420 | } 421 | } 422 | 423 | /** 424 | * Loads the given class or interface. 425 | * 426 | * @param string $class The name of the class 427 | * @return true|null True if loaded, null otherwise 428 | */ 429 | public function loadClass($class) 430 | { 431 | if ($file = $this->findFile($class)) { 432 | $includeFile = self::$includeFile; 433 | $includeFile($file); 434 | 435 | return true; 436 | } 437 | 438 | return null; 439 | } 440 | 441 | /** 442 | * Finds the path to the file where the class is defined. 443 | * 444 | * @param string $class The name of the class 445 | * 446 | * @return string|false The path if found, false otherwise 447 | */ 448 | public function findFile($class) 449 | { 450 | // class map lookup 451 | if (isset($this->classMap[$class])) { 452 | return $this->classMap[$class]; 453 | } 454 | if ($this->classMapAuthoritative || isset($this->missingClasses[$class])) { 455 | return false; 456 | } 457 | if (null !== $this->apcuPrefix) { 458 | $file = apcu_fetch($this->apcuPrefix.$class, $hit); 459 | if ($hit) { 460 | return $file; 461 | } 462 | } 463 | 464 | $file = $this->findFileWithExtension($class, '.php'); 465 | 466 | // Search for Hack files if we are running on HHVM 467 | if (false === $file && defined('HHVM_VERSION')) { 468 | $file = $this->findFileWithExtension($class, '.hh'); 469 | } 470 | 471 | if (null !== $this->apcuPrefix) { 472 | apcu_add($this->apcuPrefix.$class, $file); 473 | } 474 | 475 | if (false === $file) { 476 | // Remember that this class does not exist. 477 | $this->missingClasses[$class] = true; 478 | } 479 | 480 | return $file; 481 | } 482 | 483 | /** 484 | * Returns the currently registered loaders indexed by their corresponding vendor directories. 485 | * 486 | * @return self[] 487 | */ 488 | public static function getRegisteredLoaders() 489 | { 490 | return self::$registeredLoaders; 491 | } 492 | 493 | /** 494 | * @param string $class 495 | * @param string $ext 496 | * @return string|false 497 | */ 498 | private function findFileWithExtension($class, $ext) 499 | { 500 | // PSR-4 lookup 501 | $logicalPathPsr4 = strtr($class, '\\', DIRECTORY_SEPARATOR) . $ext; 502 | 503 | $first = $class[0]; 504 | if (isset($this->prefixLengthsPsr4[$first])) { 505 | $subPath = $class; 506 | while (false !== $lastPos = strrpos($subPath, '\\')) { 507 | $subPath = substr($subPath, 0, $lastPos); 508 | $search = $subPath . '\\'; 509 | if (isset($this->prefixDirsPsr4[$search])) { 510 | $pathEnd = DIRECTORY_SEPARATOR . substr($logicalPathPsr4, $lastPos + 1); 511 | foreach ($this->prefixDirsPsr4[$search] as $dir) { 512 | if (file_exists($file = $dir . $pathEnd)) { 513 | return $file; 514 | } 515 | } 516 | } 517 | } 518 | } 519 | 520 | // PSR-4 fallback dirs 521 | foreach ($this->fallbackDirsPsr4 as $dir) { 522 | if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr4)) { 523 | return $file; 524 | } 525 | } 526 | 527 | // PSR-0 lookup 528 | if (false !== $pos = strrpos($class, '\\')) { 529 | // namespaced class name 530 | $logicalPathPsr0 = substr($logicalPathPsr4, 0, $pos + 1) 531 | . strtr(substr($logicalPathPsr4, $pos + 1), '_', DIRECTORY_SEPARATOR); 532 | } else { 533 | // PEAR-like class name 534 | $logicalPathPsr0 = strtr($class, '_', DIRECTORY_SEPARATOR) . $ext; 535 | } 536 | 537 | if (isset($this->prefixesPsr0[$first])) { 538 | foreach ($this->prefixesPsr0[$first] as $prefix => $dirs) { 539 | if (0 === strpos($class, $prefix)) { 540 | foreach ($dirs as $dir) { 541 | if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) { 542 | return $file; 543 | } 544 | } 545 | } 546 | } 547 | } 548 | 549 | // PSR-0 fallback dirs 550 | foreach ($this->fallbackDirsPsr0 as $dir) { 551 | if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) { 552 | return $file; 553 | } 554 | } 555 | 556 | // PSR-0 include paths. 557 | if ($this->useIncludePath && $file = stream_resolve_include_path($logicalPathPsr0)) { 558 | return $file; 559 | } 560 | 561 | return false; 562 | } 563 | 564 | /** 565 | * @return void 566 | */ 567 | private static function initializeIncludeClosure() 568 | { 569 | if (self::$includeFile !== null) { 570 | return; 571 | } 572 | 573 | /** 574 | * Scope isolated include. 575 | * 576 | * Prevents access to $this/self from included files. 577 | * 578 | * @param string $file 579 | * @return void 580 | */ 581 | self::$includeFile = \Closure::bind(static function($file) { 582 | include $file; 583 | }, null, null); 584 | } 585 | } 586 | --------------------------------------------------------------------------------