├── .gitignore ├── .travis.yml ├── README.md ├── bin ├── setup-wp-redis.sh └── test-wp-redis.sh ├── class-wp-predis-decorator.php ├── composer.json ├── composer.lock ├── functions.php ├── object-cache.php ├── phpcs.ruleset.xml ├── phpunit.xml └── tests ├── bootstrap-wp-predis.php ├── bootstrap.php ├── fixtures ├── phpredis-info.php └── predis-info.php ├── test-functions.php └── test-wp-predis-decorator.php /.gitignore: -------------------------------------------------------------------------------- 1 | vendor 2 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | sudo: false 2 | dist: trusty 3 | 4 | language: php 5 | 6 | notifications: 7 | email: 8 | on_success: never 9 | on_failure: change 10 | 11 | branches: 12 | only: 13 | - master 14 | 15 | cache: 16 | - composer 17 | - $HOME/.composer/cache 18 | 19 | matrix: 20 | fast_finish: true 21 | include: 22 | - php: nightly 23 | - php: 7.4 24 | - php: 7.3 25 | - php: 7.2 26 | - php: 7.1 27 | allow_failures: 28 | - php: nightly 29 | 30 | services: 31 | - redis-server 32 | addons: 33 | apt: 34 | packages: 35 | - realpath 36 | 37 | install: 38 | - composer config platform.php $(phpenv version-name) 39 | - composer install 40 | 41 | before_script: 42 | - export PATH="./vendor/bin:$PATH" 43 | - echo 'extension = "redis.so"' >> ~/.phpenv/versions/$(phpenv version-name)/etc/php.ini 44 | - | 45 | if [[ "$WP_TRAVISCI" == "phpcs" ]] ; then 46 | export PATH="$HOME/.composer/vendor/bin:$PATH" 47 | composer global require wp-coding-standards/wpcs 48 | phpcs --config-set installed_paths $HOME/.composer/vendor/wp-coding-standards/wpcs 49 | fi 50 | - bin/setup-wp-redis.sh 51 | 52 | script: 53 | - phpunit 54 | - | 55 | if [[ "$WP_TRAVISCI" == "phpcs" ]] ; then 56 | phpcs --standard=phpcs.ruleset.xml $(find . -name '*.php') 57 | fi 58 | - bin/test-wp-redis.sh 59 | - vendor/bin/phpunit --coverage-clover=coverage.xml 60 | 61 | after_success: 62 | - bash <(curl -s https://codecov.io/bash) 63 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | 7 | 15 | 16 | 17 | 20 | 23 | 24 |
4 | WP Redis - Predis Client
5 | An alternative Redis client for use with WP Redis. Enables TLS connections. 6 |
8 | 9 | Build status 10 | 11 | 12 | Codecov 13 | 14 |
18 | A Human Made project. Maintained by @nathanielks. 19 | 21 | 22 |
25 | 26 | # WP Redis - Predis Client 27 | 28 | This is a package that enables the use of [Predis](https://github.com/nrk/predis/) as a Redis Client as opposed to PHPRedis for [WP Redis](https://github.com/pantheon-systems/wp-redis/). Predis has the distinct advantage of connecting to Redis via TLS, encrypting traffic in-transit. Requires WP Redis >= 0.7.0. 29 | 30 | ## Getting Started 31 | 32 | ### Requiring Files 33 | #### Composer 34 | 35 | When using Composer, `functions.php` file will automatically be loaded whenever you include Composer's autoloader in your project. 36 | 37 | #### Manually Requiring 38 | 39 | The only file needing `require_once`ing for WP Predis to work correctly is `functions.php` (which is automatically included via `vendor/autoload.php`, which is generated by Composer). Download this repo somewhere in your project, run `composer install`, and include `vendor/autoload.php` somewhere early (such as `wp-config.php`): 40 | 41 | ``` 42 | require_once '/path/to/wp-redis-predis-client/vendor/autoload.php'; 43 | ``` 44 | 45 | ### Object Cache stub 46 | 47 | 48 | Now that files have been included, it's recommended you use the included [`object-cache.php`](object-cache.php) file instead of the one included with WP Redis. It will add the required filters for WP Predis to work and then include WP Redis' `object-cache.php` file. Once `object-cache.php` is in `wp-content` (or whatever content directory you are using), you're good to go! 49 | 50 | ### Configuring Predis 51 | 52 | WP Redis - Predis Client adheres to WP Redis' [configuration details](https://github.com/pantheon-systems/wp-redis#installation). Predis also takes an additional argument, `ssl`, for configuring TLS connections. See PHP's [SSL Context options](http://php.net/manual/en/context.ssl.php) for more details. 53 | 54 | 55 | ```php 56 | global $redis_server; 57 | $redis_server = array( 58 | 'host' => '127.0.0.1', 59 | 'port' => 6379, 60 | 'ssl' => array( 61 | 'local_cert' => '/path/to/certificate_and_key.pem', 62 | 'verify_peer' => true, 63 | ), 64 | ); 65 | ``` 66 | 67 | 68 | -------------------------------------------------------------------------------- /bin/setup-wp-redis.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | WP_REDIS=/tmp/wp-redis 4 | MYSQL_DB="${MYSQL_DB:-wordpress_test}" 5 | MYSQL_USER="${MYSQL_USER:-root}" 6 | MYSQL_PASS="${MYSQL_PASS:-}" 7 | MYSQL_HOST="${MYSQL_HOST:-localhost}" 8 | 9 | git clone --single-branch --depth 1 https://github.com/pantheon-systems/wp-redis.git ${WP_REDIS} 10 | 11 | cd "${WP_REDIS}" || exit 12 | composer install 13 | bash bin/install-wp-tests.sh "${MYSQL_DB}" "${MYSQL_USER}" "${MYSQL_PASS}" "${MYSQL_HOST}" latest 14 | -------------------------------------------------------------------------------- /bin/test-wp-redis.sh: -------------------------------------------------------------------------------- 1 | #! /usr/bin/env bash 2 | SCRIPT="$(realpath "$0")" 3 | SCRIPTPATH="$(dirname "$SCRIPT")" 4 | WP_PREDIS="${SCRIPTPATH}/.." 5 | WP_REDIS=/tmp/wp-redis 6 | WP_TESTS=/tmp/wordpress-tests-lib 7 | PHPUNIT="${WP_PREDIS}/vendor/bin/phpunit" 8 | BOOTSTRAP_FILENAME="bootstrap-wp-predis.php" 9 | BOOTSTRAP_FILE="${WP_PREDIS}/tests/${BOOTSTRAP_FILENAME}" 10 | REQUIRE_STATEMENT="require_once dirname( __FILE__ ) . '/${BOOTSTRAP_FILENAME}';" 11 | TESTS_BOOTSTRAP="${WP_TESTS}/${BOOTSTRAP_FILENAME}" 12 | TESTS_CONFIG="${WP_TESTS}/wp-tests-config.php" 13 | 14 | # If wp-predis-bootstrap.php doesn't exist in the tests lib folder, copy it 15 | # there 16 | if [[ ! -f "${TESTS_BOOTSTRAP}" || -n "${FORCE_COPY}" ]]; then 17 | echo "Copying ${BOOTSTRAP_FILE} to ${TESTS_BOOTSTRAP}" 18 | cp "${BOOTSTRAP_FILE}" "${TESTS_BOOTSTRAP}" 19 | else 20 | echo "${TESTS_BOOTSTRAP} exists, not copying in place." 21 | fi 22 | 23 | # if the wp-predis-bootstrap.php isn't required in wp-tests-config.php, append 24 | # it to the file 25 | if ! grep -Fxq "${REQUIRE_STATEMENT}" "${TESTS_CONFIG}"; then 26 | echo "Appending REQUIRE_STATEMENT to ${TESTS_CONFIG}" 27 | echo "${REQUIRE_STATEMENT}" | tee --append "${TESTS_CONFIG}" 28 | else 29 | echo "REQUIRE_STATEMENT exists in ${TESTS_CONFIG}" 30 | fi 31 | 32 | # Let's test WP Redis with Predis as the adapter! 33 | export WP_PREDIS_DIR="${WP_PREDIS}" 34 | (cd "${WP_REDIS}" && eval "$PHPUNIT") 35 | -------------------------------------------------------------------------------- /class-wp-predis-decorator.php: -------------------------------------------------------------------------------- 1 | client = $client; 30 | } 31 | 32 | public function info( $section = null ) { 33 | $info = $this->client->info(); 34 | return $this->transform_info( $info ); 35 | } 36 | 37 | public function close() { 38 | return $this->client->disconnect(); 39 | } 40 | 41 | public function transform_info( $info ) { 42 | // let's pop this off because special formatting is required` 43 | $keyspace = $info['Keyspace']; 44 | unset( $info['Keyspace'] ); 45 | 46 | $newInfo = array_reduce( $info, function( $carry, $item ) { 47 | return array_merge( $carry, $item ); 48 | }, array()); 49 | 50 | foreach ( $keyspace as $db => $values ) { 51 | $newInfo[ $db ] = str_replace( '&', ',', http_build_query( $values ) ); 52 | } 53 | 54 | return $newInfo; 55 | } 56 | 57 | public function __call( $method_name, $args ) { 58 | // Optionally prevent flushing on non-cli. 59 | if ( in_array( strtolower( $method_name ), [ 'flushdb', 'flushall' ], true ) ) { 60 | $trace = wp_debug_backtrace_summary(); 61 | error_log( sprintf( 'wp_cache_flush() requested from ' . $trace ) ); 62 | 63 | /** 64 | * Filter whether to allow flushing. By default, only allowed on the CLI. 65 | * 66 | * @param bool True to permit flushing, false to disallow it and return immediately. 67 | */ 68 | $allowed = apply_filters( 'wp_cache_flush_allowed', 'cli' === php_sapi_name() ); 69 | if ( ! $allowed ) { 70 | trigger_error( sprintf( 'wp_cache_flush() is only allowed via WP CLI. Called from %s', $trace ), E_USER_WARNING ); 71 | return false; 72 | } 73 | } 74 | 75 | // TODO perhaps we wrap this in a try/catch and return false when 76 | // there's an exception? 77 | $start = microtime( true ); 78 | $value = call_user_func_array( array( $this->client, $method_name ), $args ); 79 | $this->time_spent += microtime( true ) - $start; 80 | $returns = $value; 81 | 82 | $lowered = strtolower( $method_name ); 83 | if ( in_array( $lowered, $this->toBool, true ) ) { 84 | $returns = (bool) $value; 85 | } 86 | 87 | if ( in_array( $lowered, $this->nullToBool, true ) ) { 88 | $returns = null === $value ? false : $value; 89 | } 90 | 91 | return $returns; 92 | } 93 | } 94 | -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "humanmade/wp-redis-predis-client", 3 | "autoload": { 4 | "files": ["functions.php"] 5 | }, 6 | "require": { 7 | "predis/predis": "~1.1" 8 | }, 9 | "require-dev": { 10 | "phpunit/phpunit": "^7.1.4" 11 | }, 12 | "config": { 13 | "platform": { 14 | "php": "7.1.0" 15 | } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /composer.lock: -------------------------------------------------------------------------------- 1 | { 2 | "_readme": [ 3 | "This file locks the dependencies of your project to a known state", 4 | "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", 5 | "This file is @generated automatically" 6 | ], 7 | "content-hash": "96013fe675bb12d230f726457f79d82e", 8 | "packages": [ 9 | { 10 | "name": "predis/predis", 11 | "version": "v1.1.7", 12 | "source": { 13 | "type": "git", 14 | "url": "https://github.com/predis/predis.git", 15 | "reference": "b240daa106d4e02f0c5b7079b41e31ddf66fddf8" 16 | }, 17 | "dist": { 18 | "type": "zip", 19 | "url": "https://api.github.com/repos/predis/predis/zipball/b240daa106d4e02f0c5b7079b41e31ddf66fddf8", 20 | "reference": "b240daa106d4e02f0c5b7079b41e31ddf66fddf8", 21 | "shasum": "" 22 | }, 23 | "require": { 24 | "php": ">=5.3.9" 25 | }, 26 | "require-dev": { 27 | "phpunit/phpunit": "~4.8" 28 | }, 29 | "suggest": { 30 | "ext-curl": "Allows access to Webdis when paired with phpiredis", 31 | "ext-phpiredis": "Allows faster serialization and deserialization of the Redis protocol" 32 | }, 33 | "type": "library", 34 | "autoload": { 35 | "psr-4": { 36 | "Predis\\": "src/" 37 | } 38 | }, 39 | "notification-url": "https://packagist.org/downloads/", 40 | "license": [ 41 | "MIT" 42 | ], 43 | "authors": [ 44 | { 45 | "name": "Daniele Alessandri", 46 | "email": "suppakilla@gmail.com", 47 | "homepage": "http://clorophilla.net", 48 | "role": "Creator & Maintainer" 49 | }, 50 | { 51 | "name": "Till Krüss", 52 | "homepage": "https://till.im", 53 | "role": "Maintainer" 54 | } 55 | ], 56 | "description": "Flexible and feature-complete Redis client for PHP and HHVM", 57 | "homepage": "http://github.com/predis/predis", 58 | "keywords": [ 59 | "nosql", 60 | "predis", 61 | "redis" 62 | ], 63 | "support": { 64 | "issues": "https://github.com/predis/predis/issues", 65 | "source": "https://github.com/predis/predis/tree/v1.1.7" 66 | }, 67 | "funding": [ 68 | { 69 | "url": "https://github.com/sponsors/tillkruss", 70 | "type": "github" 71 | } 72 | ], 73 | "time": "2021-04-04T19:34:46+00:00" 74 | } 75 | ], 76 | "packages-dev": [ 77 | { 78 | "name": "doctrine/instantiator", 79 | "version": "1.4.0", 80 | "source": { 81 | "type": "git", 82 | "url": "https://github.com/doctrine/instantiator.git", 83 | "reference": "d56bf6102915de5702778fe20f2de3b2fe570b5b" 84 | }, 85 | "dist": { 86 | "type": "zip", 87 | "url": "https://api.github.com/repos/doctrine/instantiator/zipball/d56bf6102915de5702778fe20f2de3b2fe570b5b", 88 | "reference": "d56bf6102915de5702778fe20f2de3b2fe570b5b", 89 | "shasum": "" 90 | }, 91 | "require": { 92 | "php": "^7.1 || ^8.0" 93 | }, 94 | "require-dev": { 95 | "doctrine/coding-standard": "^8.0", 96 | "ext-pdo": "*", 97 | "ext-phar": "*", 98 | "phpbench/phpbench": "^0.13 || 1.0.0-alpha2", 99 | "phpstan/phpstan": "^0.12", 100 | "phpstan/phpstan-phpunit": "^0.12", 101 | "phpunit/phpunit": "^7.0 || ^8.0 || ^9.0" 102 | }, 103 | "type": "library", 104 | "autoload": { 105 | "psr-4": { 106 | "Doctrine\\Instantiator\\": "src/Doctrine/Instantiator/" 107 | } 108 | }, 109 | "notification-url": "https://packagist.org/downloads/", 110 | "license": [ 111 | "MIT" 112 | ], 113 | "authors": [ 114 | { 115 | "name": "Marco Pivetta", 116 | "email": "ocramius@gmail.com", 117 | "homepage": "https://ocramius.github.io/" 118 | } 119 | ], 120 | "description": "A small, lightweight utility to instantiate objects in PHP without invoking their constructors", 121 | "homepage": "https://www.doctrine-project.org/projects/instantiator.html", 122 | "keywords": [ 123 | "constructor", 124 | "instantiate" 125 | ], 126 | "support": { 127 | "issues": "https://github.com/doctrine/instantiator/issues", 128 | "source": "https://github.com/doctrine/instantiator/tree/1.4.0" 129 | }, 130 | "funding": [ 131 | { 132 | "url": "https://www.doctrine-project.org/sponsorship.html", 133 | "type": "custom" 134 | }, 135 | { 136 | "url": "https://www.patreon.com/phpdoctrine", 137 | "type": "patreon" 138 | }, 139 | { 140 | "url": "https://tidelift.com/funding/github/packagist/doctrine%2Finstantiator", 141 | "type": "tidelift" 142 | } 143 | ], 144 | "time": "2020-11-10T18:47:58+00:00" 145 | }, 146 | { 147 | "name": "myclabs/deep-copy", 148 | "version": "1.10.2", 149 | "source": { 150 | "type": "git", 151 | "url": "https://github.com/myclabs/DeepCopy.git", 152 | "reference": "776f831124e9c62e1a2c601ecc52e776d8bb7220" 153 | }, 154 | "dist": { 155 | "type": "zip", 156 | "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/776f831124e9c62e1a2c601ecc52e776d8bb7220", 157 | "reference": "776f831124e9c62e1a2c601ecc52e776d8bb7220", 158 | "shasum": "" 159 | }, 160 | "require": { 161 | "php": "^7.1 || ^8.0" 162 | }, 163 | "replace": { 164 | "myclabs/deep-copy": "self.version" 165 | }, 166 | "require-dev": { 167 | "doctrine/collections": "^1.0", 168 | "doctrine/common": "^2.6", 169 | "phpunit/phpunit": "^7.1" 170 | }, 171 | "type": "library", 172 | "autoload": { 173 | "psr-4": { 174 | "DeepCopy\\": "src/DeepCopy/" 175 | }, 176 | "files": [ 177 | "src/DeepCopy/deep_copy.php" 178 | ] 179 | }, 180 | "notification-url": "https://packagist.org/downloads/", 181 | "license": [ 182 | "MIT" 183 | ], 184 | "description": "Create deep copies (clones) of your objects", 185 | "keywords": [ 186 | "clone", 187 | "copy", 188 | "duplicate", 189 | "object", 190 | "object graph" 191 | ], 192 | "support": { 193 | "issues": "https://github.com/myclabs/DeepCopy/issues", 194 | "source": "https://github.com/myclabs/DeepCopy/tree/1.10.2" 195 | }, 196 | "funding": [ 197 | { 198 | "url": "https://tidelift.com/funding/github/packagist/myclabs/deep-copy", 199 | "type": "tidelift" 200 | } 201 | ], 202 | "time": "2020-11-13T09:40:50+00:00" 203 | }, 204 | { 205 | "name": "phar-io/manifest", 206 | "version": "1.0.3", 207 | "source": { 208 | "type": "git", 209 | "url": "https://github.com/phar-io/manifest.git", 210 | "reference": "7761fcacf03b4d4f16e7ccb606d4879ca431fcf4" 211 | }, 212 | "dist": { 213 | "type": "zip", 214 | "url": "https://api.github.com/repos/phar-io/manifest/zipball/7761fcacf03b4d4f16e7ccb606d4879ca431fcf4", 215 | "reference": "7761fcacf03b4d4f16e7ccb606d4879ca431fcf4", 216 | "shasum": "" 217 | }, 218 | "require": { 219 | "ext-dom": "*", 220 | "ext-phar": "*", 221 | "phar-io/version": "^2.0", 222 | "php": "^5.6 || ^7.0" 223 | }, 224 | "type": "library", 225 | "extra": { 226 | "branch-alias": { 227 | "dev-master": "1.0.x-dev" 228 | } 229 | }, 230 | "autoload": { 231 | "classmap": [ 232 | "src/" 233 | ] 234 | }, 235 | "notification-url": "https://packagist.org/downloads/", 236 | "license": [ 237 | "BSD-3-Clause" 238 | ], 239 | "authors": [ 240 | { 241 | "name": "Arne Blankerts", 242 | "email": "arne@blankerts.de", 243 | "role": "Developer" 244 | }, 245 | { 246 | "name": "Sebastian Heuer", 247 | "email": "sebastian@phpeople.de", 248 | "role": "Developer" 249 | }, 250 | { 251 | "name": "Sebastian Bergmann", 252 | "email": "sebastian@phpunit.de", 253 | "role": "Developer" 254 | } 255 | ], 256 | "description": "Component for reading phar.io manifest information from a PHP Archive (PHAR)", 257 | "support": { 258 | "issues": "https://github.com/phar-io/manifest/issues", 259 | "source": "https://github.com/phar-io/manifest/tree/master" 260 | }, 261 | "time": "2018-07-08T19:23:20+00:00" 262 | }, 263 | { 264 | "name": "phar-io/version", 265 | "version": "2.0.1", 266 | "source": { 267 | "type": "git", 268 | "url": "https://github.com/phar-io/version.git", 269 | "reference": "45a2ec53a73c70ce41d55cedef9063630abaf1b6" 270 | }, 271 | "dist": { 272 | "type": "zip", 273 | "url": "https://api.github.com/repos/phar-io/version/zipball/45a2ec53a73c70ce41d55cedef9063630abaf1b6", 274 | "reference": "45a2ec53a73c70ce41d55cedef9063630abaf1b6", 275 | "shasum": "" 276 | }, 277 | "require": { 278 | "php": "^5.6 || ^7.0" 279 | }, 280 | "type": "library", 281 | "autoload": { 282 | "classmap": [ 283 | "src/" 284 | ] 285 | }, 286 | "notification-url": "https://packagist.org/downloads/", 287 | "license": [ 288 | "BSD-3-Clause" 289 | ], 290 | "authors": [ 291 | { 292 | "name": "Arne Blankerts", 293 | "email": "arne@blankerts.de", 294 | "role": "Developer" 295 | }, 296 | { 297 | "name": "Sebastian Heuer", 298 | "email": "sebastian@phpeople.de", 299 | "role": "Developer" 300 | }, 301 | { 302 | "name": "Sebastian Bergmann", 303 | "email": "sebastian@phpunit.de", 304 | "role": "Developer" 305 | } 306 | ], 307 | "description": "Library for handling version information and constraints", 308 | "support": { 309 | "issues": "https://github.com/phar-io/version/issues", 310 | "source": "https://github.com/phar-io/version/tree/master" 311 | }, 312 | "time": "2018-07-08T19:19:57+00:00" 313 | }, 314 | { 315 | "name": "phpdocumentor/reflection-common", 316 | "version": "2.1.0", 317 | "source": { 318 | "type": "git", 319 | "url": "https://github.com/phpDocumentor/ReflectionCommon.git", 320 | "reference": "6568f4687e5b41b054365f9ae03fcb1ed5f2069b" 321 | }, 322 | "dist": { 323 | "type": "zip", 324 | "url": "https://api.github.com/repos/phpDocumentor/ReflectionCommon/zipball/6568f4687e5b41b054365f9ae03fcb1ed5f2069b", 325 | "reference": "6568f4687e5b41b054365f9ae03fcb1ed5f2069b", 326 | "shasum": "" 327 | }, 328 | "require": { 329 | "php": ">=7.1" 330 | }, 331 | "type": "library", 332 | "extra": { 333 | "branch-alias": { 334 | "dev-master": "2.x-dev" 335 | } 336 | }, 337 | "autoload": { 338 | "psr-4": { 339 | "phpDocumentor\\Reflection\\": "src/" 340 | } 341 | }, 342 | "notification-url": "https://packagist.org/downloads/", 343 | "license": [ 344 | "MIT" 345 | ], 346 | "authors": [ 347 | { 348 | "name": "Jaap van Otterdijk", 349 | "email": "opensource@ijaap.nl" 350 | } 351 | ], 352 | "description": "Common reflection classes used by phpdocumentor to reflect the code structure", 353 | "homepage": "http://www.phpdoc.org", 354 | "keywords": [ 355 | "FQSEN", 356 | "phpDocumentor", 357 | "phpdoc", 358 | "reflection", 359 | "static analysis" 360 | ], 361 | "support": { 362 | "issues": "https://github.com/phpDocumentor/ReflectionCommon/issues", 363 | "source": "https://github.com/phpDocumentor/ReflectionCommon/tree/master" 364 | }, 365 | "time": "2020-04-27T09:25:28+00:00" 366 | }, 367 | { 368 | "name": "phpdocumentor/reflection-docblock", 369 | "version": "4.3.4", 370 | "source": { 371 | "type": "git", 372 | "url": "https://github.com/phpDocumentor/ReflectionDocBlock.git", 373 | "reference": "da3fd972d6bafd628114f7e7e036f45944b62e9c" 374 | }, 375 | "dist": { 376 | "type": "zip", 377 | "url": "https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/da3fd972d6bafd628114f7e7e036f45944b62e9c", 378 | "reference": "da3fd972d6bafd628114f7e7e036f45944b62e9c", 379 | "shasum": "" 380 | }, 381 | "require": { 382 | "php": "^7.0", 383 | "phpdocumentor/reflection-common": "^1.0.0 || ^2.0.0", 384 | "phpdocumentor/type-resolver": "~0.4 || ^1.0.0", 385 | "webmozart/assert": "^1.0" 386 | }, 387 | "require-dev": { 388 | "doctrine/instantiator": "^1.0.5", 389 | "mockery/mockery": "^1.0", 390 | "phpdocumentor/type-resolver": "0.4.*", 391 | "phpunit/phpunit": "^6.4" 392 | }, 393 | "type": "library", 394 | "extra": { 395 | "branch-alias": { 396 | "dev-master": "4.x-dev" 397 | } 398 | }, 399 | "autoload": { 400 | "psr-4": { 401 | "phpDocumentor\\Reflection\\": [ 402 | "src/" 403 | ] 404 | } 405 | }, 406 | "notification-url": "https://packagist.org/downloads/", 407 | "license": [ 408 | "MIT" 409 | ], 410 | "authors": [ 411 | { 412 | "name": "Mike van Riel", 413 | "email": "me@mikevanriel.com" 414 | } 415 | ], 416 | "description": "With this component, a library can provide support for annotations via DocBlocks or otherwise retrieve information that is embedded in a DocBlock.", 417 | "support": { 418 | "issues": "https://github.com/phpDocumentor/ReflectionDocBlock/issues", 419 | "source": "https://github.com/phpDocumentor/ReflectionDocBlock/tree/release/4.x" 420 | }, 421 | "time": "2019-12-28T18:55:12+00:00" 422 | }, 423 | { 424 | "name": "phpdocumentor/type-resolver", 425 | "version": "1.0.1", 426 | "source": { 427 | "type": "git", 428 | "url": "https://github.com/phpDocumentor/TypeResolver.git", 429 | "reference": "2e32a6d48972b2c1976ed5d8967145b6cec4a4a9" 430 | }, 431 | "dist": { 432 | "type": "zip", 433 | "url": "https://api.github.com/repos/phpDocumentor/TypeResolver/zipball/2e32a6d48972b2c1976ed5d8967145b6cec4a4a9", 434 | "reference": "2e32a6d48972b2c1976ed5d8967145b6cec4a4a9", 435 | "shasum": "" 436 | }, 437 | "require": { 438 | "php": "^7.1", 439 | "phpdocumentor/reflection-common": "^2.0" 440 | }, 441 | "require-dev": { 442 | "ext-tokenizer": "^7.1", 443 | "mockery/mockery": "~1", 444 | "phpunit/phpunit": "^7.0" 445 | }, 446 | "type": "library", 447 | "extra": { 448 | "branch-alias": { 449 | "dev-master": "1.x-dev" 450 | } 451 | }, 452 | "autoload": { 453 | "psr-4": { 454 | "phpDocumentor\\Reflection\\": "src" 455 | } 456 | }, 457 | "notification-url": "https://packagist.org/downloads/", 458 | "license": [ 459 | "MIT" 460 | ], 461 | "authors": [ 462 | { 463 | "name": "Mike van Riel", 464 | "email": "me@mikevanriel.com" 465 | } 466 | ], 467 | "description": "A PSR-5 based resolver of Class names, Types and Structural Element Names", 468 | "support": { 469 | "issues": "https://github.com/phpDocumentor/TypeResolver/issues", 470 | "source": "https://github.com/phpDocumentor/TypeResolver/tree/0.7.2" 471 | }, 472 | "time": "2019-08-22T18:11:29+00:00" 473 | }, 474 | { 475 | "name": "phpspec/prophecy", 476 | "version": "v1.10.3", 477 | "source": { 478 | "type": "git", 479 | "url": "https://github.com/phpspec/prophecy.git", 480 | "reference": "451c3cd1418cf640de218914901e51b064abb093" 481 | }, 482 | "dist": { 483 | "type": "zip", 484 | "url": "https://api.github.com/repos/phpspec/prophecy/zipball/451c3cd1418cf640de218914901e51b064abb093", 485 | "reference": "451c3cd1418cf640de218914901e51b064abb093", 486 | "shasum": "" 487 | }, 488 | "require": { 489 | "doctrine/instantiator": "^1.0.2", 490 | "php": "^5.3|^7.0", 491 | "phpdocumentor/reflection-docblock": "^2.0|^3.0.2|^4.0|^5.0", 492 | "sebastian/comparator": "^1.2.3|^2.0|^3.0|^4.0", 493 | "sebastian/recursion-context": "^1.0|^2.0|^3.0|^4.0" 494 | }, 495 | "require-dev": { 496 | "phpspec/phpspec": "^2.5 || ^3.2", 497 | "phpunit/phpunit": "^4.8.35 || ^5.7 || ^6.5 || ^7.1" 498 | }, 499 | "type": "library", 500 | "extra": { 501 | "branch-alias": { 502 | "dev-master": "1.10.x-dev" 503 | } 504 | }, 505 | "autoload": { 506 | "psr-4": { 507 | "Prophecy\\": "src/Prophecy" 508 | } 509 | }, 510 | "notification-url": "https://packagist.org/downloads/", 511 | "license": [ 512 | "MIT" 513 | ], 514 | "authors": [ 515 | { 516 | "name": "Konstantin Kudryashov", 517 | "email": "ever.zet@gmail.com", 518 | "homepage": "http://everzet.com" 519 | }, 520 | { 521 | "name": "Marcello Duarte", 522 | "email": "marcello.duarte@gmail.com" 523 | } 524 | ], 525 | "description": "Highly opinionated mocking framework for PHP 5.3+", 526 | "homepage": "https://github.com/phpspec/prophecy", 527 | "keywords": [ 528 | "Double", 529 | "Dummy", 530 | "fake", 531 | "mock", 532 | "spy", 533 | "stub" 534 | ], 535 | "support": { 536 | "issues": "https://github.com/phpspec/prophecy/issues", 537 | "source": "https://github.com/phpspec/prophecy/tree/v1.10.3" 538 | }, 539 | "time": "2020-03-05T15:02:03+00:00" 540 | }, 541 | { 542 | "name": "phpunit/php-code-coverage", 543 | "version": "6.1.4", 544 | "source": { 545 | "type": "git", 546 | "url": "https://github.com/sebastianbergmann/php-code-coverage.git", 547 | "reference": "807e6013b00af69b6c5d9ceb4282d0393dbb9d8d" 548 | }, 549 | "dist": { 550 | "type": "zip", 551 | "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/807e6013b00af69b6c5d9ceb4282d0393dbb9d8d", 552 | "reference": "807e6013b00af69b6c5d9ceb4282d0393dbb9d8d", 553 | "shasum": "" 554 | }, 555 | "require": { 556 | "ext-dom": "*", 557 | "ext-xmlwriter": "*", 558 | "php": "^7.1", 559 | "phpunit/php-file-iterator": "^2.0", 560 | "phpunit/php-text-template": "^1.2.1", 561 | "phpunit/php-token-stream": "^3.0", 562 | "sebastian/code-unit-reverse-lookup": "^1.0.1", 563 | "sebastian/environment": "^3.1 || ^4.0", 564 | "sebastian/version": "^2.0.1", 565 | "theseer/tokenizer": "^1.1" 566 | }, 567 | "require-dev": { 568 | "phpunit/phpunit": "^7.0" 569 | }, 570 | "suggest": { 571 | "ext-xdebug": "^2.6.0" 572 | }, 573 | "type": "library", 574 | "extra": { 575 | "branch-alias": { 576 | "dev-master": "6.1-dev" 577 | } 578 | }, 579 | "autoload": { 580 | "classmap": [ 581 | "src/" 582 | ] 583 | }, 584 | "notification-url": "https://packagist.org/downloads/", 585 | "license": [ 586 | "BSD-3-Clause" 587 | ], 588 | "authors": [ 589 | { 590 | "name": "Sebastian Bergmann", 591 | "email": "sebastian@phpunit.de", 592 | "role": "lead" 593 | } 594 | ], 595 | "description": "Library that provides collection, processing, and rendering functionality for PHP code coverage information.", 596 | "homepage": "https://github.com/sebastianbergmann/php-code-coverage", 597 | "keywords": [ 598 | "coverage", 599 | "testing", 600 | "xunit" 601 | ], 602 | "support": { 603 | "issues": "https://github.com/sebastianbergmann/php-code-coverage/issues", 604 | "source": "https://github.com/sebastianbergmann/php-code-coverage/tree/master" 605 | }, 606 | "time": "2018-10-31T16:06:48+00:00" 607 | }, 608 | { 609 | "name": "phpunit/php-file-iterator", 610 | "version": "2.0.3", 611 | "source": { 612 | "type": "git", 613 | "url": "https://github.com/sebastianbergmann/php-file-iterator.git", 614 | "reference": "4b49fb70f067272b659ef0174ff9ca40fdaa6357" 615 | }, 616 | "dist": { 617 | "type": "zip", 618 | "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/4b49fb70f067272b659ef0174ff9ca40fdaa6357", 619 | "reference": "4b49fb70f067272b659ef0174ff9ca40fdaa6357", 620 | "shasum": "" 621 | }, 622 | "require": { 623 | "php": ">=7.1" 624 | }, 625 | "require-dev": { 626 | "phpunit/phpunit": "^8.5" 627 | }, 628 | "type": "library", 629 | "extra": { 630 | "branch-alias": { 631 | "dev-master": "2.0.x-dev" 632 | } 633 | }, 634 | "autoload": { 635 | "classmap": [ 636 | "src/" 637 | ] 638 | }, 639 | "notification-url": "https://packagist.org/downloads/", 640 | "license": [ 641 | "BSD-3-Clause" 642 | ], 643 | "authors": [ 644 | { 645 | "name": "Sebastian Bergmann", 646 | "email": "sebastian@phpunit.de", 647 | "role": "lead" 648 | } 649 | ], 650 | "description": "FilterIterator implementation that filters files based on a list of suffixes.", 651 | "homepage": "https://github.com/sebastianbergmann/php-file-iterator/", 652 | "keywords": [ 653 | "filesystem", 654 | "iterator" 655 | ], 656 | "support": { 657 | "issues": "https://github.com/sebastianbergmann/php-file-iterator/issues", 658 | "source": "https://github.com/sebastianbergmann/php-file-iterator/tree/2.0.3" 659 | }, 660 | "funding": [ 661 | { 662 | "url": "https://github.com/sebastianbergmann", 663 | "type": "github" 664 | } 665 | ], 666 | "time": "2020-11-30T08:25:21+00:00" 667 | }, 668 | { 669 | "name": "phpunit/php-text-template", 670 | "version": "1.2.1", 671 | "source": { 672 | "type": "git", 673 | "url": "https://github.com/sebastianbergmann/php-text-template.git", 674 | "reference": "31f8b717e51d9a2afca6c9f046f5d69fc27c8686" 675 | }, 676 | "dist": { 677 | "type": "zip", 678 | "url": "https://api.github.com/repos/sebastianbergmann/php-text-template/zipball/31f8b717e51d9a2afca6c9f046f5d69fc27c8686", 679 | "reference": "31f8b717e51d9a2afca6c9f046f5d69fc27c8686", 680 | "shasum": "" 681 | }, 682 | "require": { 683 | "php": ">=5.3.3" 684 | }, 685 | "type": "library", 686 | "autoload": { 687 | "classmap": [ 688 | "src/" 689 | ] 690 | }, 691 | "notification-url": "https://packagist.org/downloads/", 692 | "license": [ 693 | "BSD-3-Clause" 694 | ], 695 | "authors": [ 696 | { 697 | "name": "Sebastian Bergmann", 698 | "email": "sebastian@phpunit.de", 699 | "role": "lead" 700 | } 701 | ], 702 | "description": "Simple template engine.", 703 | "homepage": "https://github.com/sebastianbergmann/php-text-template/", 704 | "keywords": [ 705 | "template" 706 | ], 707 | "support": { 708 | "issues": "https://github.com/sebastianbergmann/php-text-template/issues", 709 | "source": "https://github.com/sebastianbergmann/php-text-template/tree/1.2.1" 710 | }, 711 | "time": "2015-06-21T13:50:34+00:00" 712 | }, 713 | { 714 | "name": "phpunit/php-timer", 715 | "version": "2.1.3", 716 | "source": { 717 | "type": "git", 718 | "url": "https://github.com/sebastianbergmann/php-timer.git", 719 | "reference": "2454ae1765516d20c4ffe103d85a58a9a3bd5662" 720 | }, 721 | "dist": { 722 | "type": "zip", 723 | "url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/2454ae1765516d20c4ffe103d85a58a9a3bd5662", 724 | "reference": "2454ae1765516d20c4ffe103d85a58a9a3bd5662", 725 | "shasum": "" 726 | }, 727 | "require": { 728 | "php": ">=7.1" 729 | }, 730 | "require-dev": { 731 | "phpunit/phpunit": "^8.5" 732 | }, 733 | "type": "library", 734 | "extra": { 735 | "branch-alias": { 736 | "dev-master": "2.1-dev" 737 | } 738 | }, 739 | "autoload": { 740 | "classmap": [ 741 | "src/" 742 | ] 743 | }, 744 | "notification-url": "https://packagist.org/downloads/", 745 | "license": [ 746 | "BSD-3-Clause" 747 | ], 748 | "authors": [ 749 | { 750 | "name": "Sebastian Bergmann", 751 | "email": "sebastian@phpunit.de", 752 | "role": "lead" 753 | } 754 | ], 755 | "description": "Utility class for timing", 756 | "homepage": "https://github.com/sebastianbergmann/php-timer/", 757 | "keywords": [ 758 | "timer" 759 | ], 760 | "support": { 761 | "issues": "https://github.com/sebastianbergmann/php-timer/issues", 762 | "source": "https://github.com/sebastianbergmann/php-timer/tree/2.1.3" 763 | }, 764 | "funding": [ 765 | { 766 | "url": "https://github.com/sebastianbergmann", 767 | "type": "github" 768 | } 769 | ], 770 | "time": "2020-11-30T08:20:02+00:00" 771 | }, 772 | { 773 | "name": "phpunit/php-token-stream", 774 | "version": "3.1.2", 775 | "source": { 776 | "type": "git", 777 | "url": "https://github.com/sebastianbergmann/php-token-stream.git", 778 | "reference": "472b687829041c24b25f475e14c2f38a09edf1c2" 779 | }, 780 | "dist": { 781 | "type": "zip", 782 | "url": "https://api.github.com/repos/sebastianbergmann/php-token-stream/zipball/472b687829041c24b25f475e14c2f38a09edf1c2", 783 | "reference": "472b687829041c24b25f475e14c2f38a09edf1c2", 784 | "shasum": "" 785 | }, 786 | "require": { 787 | "ext-tokenizer": "*", 788 | "php": ">=7.1" 789 | }, 790 | "require-dev": { 791 | "phpunit/phpunit": "^7.0" 792 | }, 793 | "type": "library", 794 | "extra": { 795 | "branch-alias": { 796 | "dev-master": "3.1-dev" 797 | } 798 | }, 799 | "autoload": { 800 | "classmap": [ 801 | "src/" 802 | ] 803 | }, 804 | "notification-url": "https://packagist.org/downloads/", 805 | "license": [ 806 | "BSD-3-Clause" 807 | ], 808 | "authors": [ 809 | { 810 | "name": "Sebastian Bergmann", 811 | "email": "sebastian@phpunit.de" 812 | } 813 | ], 814 | "description": "Wrapper around PHP's tokenizer extension.", 815 | "homepage": "https://github.com/sebastianbergmann/php-token-stream/", 816 | "keywords": [ 817 | "tokenizer" 818 | ], 819 | "support": { 820 | "issues": "https://github.com/sebastianbergmann/php-token-stream/issues", 821 | "source": "https://github.com/sebastianbergmann/php-token-stream/tree/3.1.2" 822 | }, 823 | "funding": [ 824 | { 825 | "url": "https://github.com/sebastianbergmann", 826 | "type": "github" 827 | } 828 | ], 829 | "abandoned": true, 830 | "time": "2020-11-30T08:38:46+00:00" 831 | }, 832 | { 833 | "name": "phpunit/phpunit", 834 | "version": "7.5.20", 835 | "source": { 836 | "type": "git", 837 | "url": "https://github.com/sebastianbergmann/phpunit.git", 838 | "reference": "9467db479d1b0487c99733bb1e7944d32deded2c" 839 | }, 840 | "dist": { 841 | "type": "zip", 842 | "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/9467db479d1b0487c99733bb1e7944d32deded2c", 843 | "reference": "9467db479d1b0487c99733bb1e7944d32deded2c", 844 | "shasum": "" 845 | }, 846 | "require": { 847 | "doctrine/instantiator": "^1.1", 848 | "ext-dom": "*", 849 | "ext-json": "*", 850 | "ext-libxml": "*", 851 | "ext-mbstring": "*", 852 | "ext-xml": "*", 853 | "myclabs/deep-copy": "^1.7", 854 | "phar-io/manifest": "^1.0.2", 855 | "phar-io/version": "^2.0", 856 | "php": "^7.1", 857 | "phpspec/prophecy": "^1.7", 858 | "phpunit/php-code-coverage": "^6.0.7", 859 | "phpunit/php-file-iterator": "^2.0.1", 860 | "phpunit/php-text-template": "^1.2.1", 861 | "phpunit/php-timer": "^2.1", 862 | "sebastian/comparator": "^3.0", 863 | "sebastian/diff": "^3.0", 864 | "sebastian/environment": "^4.0", 865 | "sebastian/exporter": "^3.1", 866 | "sebastian/global-state": "^2.0", 867 | "sebastian/object-enumerator": "^3.0.3", 868 | "sebastian/resource-operations": "^2.0", 869 | "sebastian/version": "^2.0.1" 870 | }, 871 | "conflict": { 872 | "phpunit/phpunit-mock-objects": "*" 873 | }, 874 | "require-dev": { 875 | "ext-pdo": "*" 876 | }, 877 | "suggest": { 878 | "ext-soap": "*", 879 | "ext-xdebug": "*", 880 | "phpunit/php-invoker": "^2.0" 881 | }, 882 | "bin": [ 883 | "phpunit" 884 | ], 885 | "type": "library", 886 | "extra": { 887 | "branch-alias": { 888 | "dev-master": "7.5-dev" 889 | } 890 | }, 891 | "autoload": { 892 | "classmap": [ 893 | "src/" 894 | ] 895 | }, 896 | "notification-url": "https://packagist.org/downloads/", 897 | "license": [ 898 | "BSD-3-Clause" 899 | ], 900 | "authors": [ 901 | { 902 | "name": "Sebastian Bergmann", 903 | "email": "sebastian@phpunit.de", 904 | "role": "lead" 905 | } 906 | ], 907 | "description": "The PHP Unit Testing framework.", 908 | "homepage": "https://phpunit.de/", 909 | "keywords": [ 910 | "phpunit", 911 | "testing", 912 | "xunit" 913 | ], 914 | "support": { 915 | "issues": "https://github.com/sebastianbergmann/phpunit/issues", 916 | "source": "https://github.com/sebastianbergmann/phpunit/tree/7.5.20" 917 | }, 918 | "time": "2020-01-08T08:45:45+00:00" 919 | }, 920 | { 921 | "name": "sebastian/code-unit-reverse-lookup", 922 | "version": "1.0.2", 923 | "source": { 924 | "type": "git", 925 | "url": "https://github.com/sebastianbergmann/code-unit-reverse-lookup.git", 926 | "reference": "1de8cd5c010cb153fcd68b8d0f64606f523f7619" 927 | }, 928 | "dist": { 929 | "type": "zip", 930 | "url": "https://api.github.com/repos/sebastianbergmann/code-unit-reverse-lookup/zipball/1de8cd5c010cb153fcd68b8d0f64606f523f7619", 931 | "reference": "1de8cd5c010cb153fcd68b8d0f64606f523f7619", 932 | "shasum": "" 933 | }, 934 | "require": { 935 | "php": ">=5.6" 936 | }, 937 | "require-dev": { 938 | "phpunit/phpunit": "^8.5" 939 | }, 940 | "type": "library", 941 | "extra": { 942 | "branch-alias": { 943 | "dev-master": "1.0.x-dev" 944 | } 945 | }, 946 | "autoload": { 947 | "classmap": [ 948 | "src/" 949 | ] 950 | }, 951 | "notification-url": "https://packagist.org/downloads/", 952 | "license": [ 953 | "BSD-3-Clause" 954 | ], 955 | "authors": [ 956 | { 957 | "name": "Sebastian Bergmann", 958 | "email": "sebastian@phpunit.de" 959 | } 960 | ], 961 | "description": "Looks up which function or method a line of code belongs to", 962 | "homepage": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/", 963 | "support": { 964 | "issues": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/issues", 965 | "source": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/tree/1.0.2" 966 | }, 967 | "funding": [ 968 | { 969 | "url": "https://github.com/sebastianbergmann", 970 | "type": "github" 971 | } 972 | ], 973 | "time": "2020-11-30T08:15:22+00:00" 974 | }, 975 | { 976 | "name": "sebastian/comparator", 977 | "version": "3.0.3", 978 | "source": { 979 | "type": "git", 980 | "url": "https://github.com/sebastianbergmann/comparator.git", 981 | "reference": "1071dfcef776a57013124ff35e1fc41ccd294758" 982 | }, 983 | "dist": { 984 | "type": "zip", 985 | "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/1071dfcef776a57013124ff35e1fc41ccd294758", 986 | "reference": "1071dfcef776a57013124ff35e1fc41ccd294758", 987 | "shasum": "" 988 | }, 989 | "require": { 990 | "php": ">=7.1", 991 | "sebastian/diff": "^3.0", 992 | "sebastian/exporter": "^3.1" 993 | }, 994 | "require-dev": { 995 | "phpunit/phpunit": "^8.5" 996 | }, 997 | "type": "library", 998 | "extra": { 999 | "branch-alias": { 1000 | "dev-master": "3.0-dev" 1001 | } 1002 | }, 1003 | "autoload": { 1004 | "classmap": [ 1005 | "src/" 1006 | ] 1007 | }, 1008 | "notification-url": "https://packagist.org/downloads/", 1009 | "license": [ 1010 | "BSD-3-Clause" 1011 | ], 1012 | "authors": [ 1013 | { 1014 | "name": "Sebastian Bergmann", 1015 | "email": "sebastian@phpunit.de" 1016 | }, 1017 | { 1018 | "name": "Jeff Welch", 1019 | "email": "whatthejeff@gmail.com" 1020 | }, 1021 | { 1022 | "name": "Volker Dusch", 1023 | "email": "github@wallbash.com" 1024 | }, 1025 | { 1026 | "name": "Bernhard Schussek", 1027 | "email": "bschussek@2bepublished.at" 1028 | } 1029 | ], 1030 | "description": "Provides the functionality to compare PHP values for equality", 1031 | "homepage": "https://github.com/sebastianbergmann/comparator", 1032 | "keywords": [ 1033 | "comparator", 1034 | "compare", 1035 | "equality" 1036 | ], 1037 | "support": { 1038 | "issues": "https://github.com/sebastianbergmann/comparator/issues", 1039 | "source": "https://github.com/sebastianbergmann/comparator/tree/3.0.3" 1040 | }, 1041 | "funding": [ 1042 | { 1043 | "url": "https://github.com/sebastianbergmann", 1044 | "type": "github" 1045 | } 1046 | ], 1047 | "time": "2020-11-30T08:04:30+00:00" 1048 | }, 1049 | { 1050 | "name": "sebastian/diff", 1051 | "version": "3.0.3", 1052 | "source": { 1053 | "type": "git", 1054 | "url": "https://github.com/sebastianbergmann/diff.git", 1055 | "reference": "14f72dd46eaf2f2293cbe79c93cc0bc43161a211" 1056 | }, 1057 | "dist": { 1058 | "type": "zip", 1059 | "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/14f72dd46eaf2f2293cbe79c93cc0bc43161a211", 1060 | "reference": "14f72dd46eaf2f2293cbe79c93cc0bc43161a211", 1061 | "shasum": "" 1062 | }, 1063 | "require": { 1064 | "php": ">=7.1" 1065 | }, 1066 | "require-dev": { 1067 | "phpunit/phpunit": "^7.5 || ^8.0", 1068 | "symfony/process": "^2 || ^3.3 || ^4" 1069 | }, 1070 | "type": "library", 1071 | "extra": { 1072 | "branch-alias": { 1073 | "dev-master": "3.0-dev" 1074 | } 1075 | }, 1076 | "autoload": { 1077 | "classmap": [ 1078 | "src/" 1079 | ] 1080 | }, 1081 | "notification-url": "https://packagist.org/downloads/", 1082 | "license": [ 1083 | "BSD-3-Clause" 1084 | ], 1085 | "authors": [ 1086 | { 1087 | "name": "Sebastian Bergmann", 1088 | "email": "sebastian@phpunit.de" 1089 | }, 1090 | { 1091 | "name": "Kore Nordmann", 1092 | "email": "mail@kore-nordmann.de" 1093 | } 1094 | ], 1095 | "description": "Diff implementation", 1096 | "homepage": "https://github.com/sebastianbergmann/diff", 1097 | "keywords": [ 1098 | "diff", 1099 | "udiff", 1100 | "unidiff", 1101 | "unified diff" 1102 | ], 1103 | "support": { 1104 | "issues": "https://github.com/sebastianbergmann/diff/issues", 1105 | "source": "https://github.com/sebastianbergmann/diff/tree/3.0.3" 1106 | }, 1107 | "funding": [ 1108 | { 1109 | "url": "https://github.com/sebastianbergmann", 1110 | "type": "github" 1111 | } 1112 | ], 1113 | "time": "2020-11-30T07:59:04+00:00" 1114 | }, 1115 | { 1116 | "name": "sebastian/environment", 1117 | "version": "4.2.4", 1118 | "source": { 1119 | "type": "git", 1120 | "url": "https://github.com/sebastianbergmann/environment.git", 1121 | "reference": "d47bbbad83711771f167c72d4e3f25f7fcc1f8b0" 1122 | }, 1123 | "dist": { 1124 | "type": "zip", 1125 | "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/d47bbbad83711771f167c72d4e3f25f7fcc1f8b0", 1126 | "reference": "d47bbbad83711771f167c72d4e3f25f7fcc1f8b0", 1127 | "shasum": "" 1128 | }, 1129 | "require": { 1130 | "php": ">=7.1" 1131 | }, 1132 | "require-dev": { 1133 | "phpunit/phpunit": "^7.5" 1134 | }, 1135 | "suggest": { 1136 | "ext-posix": "*" 1137 | }, 1138 | "type": "library", 1139 | "extra": { 1140 | "branch-alias": { 1141 | "dev-master": "4.2-dev" 1142 | } 1143 | }, 1144 | "autoload": { 1145 | "classmap": [ 1146 | "src/" 1147 | ] 1148 | }, 1149 | "notification-url": "https://packagist.org/downloads/", 1150 | "license": [ 1151 | "BSD-3-Clause" 1152 | ], 1153 | "authors": [ 1154 | { 1155 | "name": "Sebastian Bergmann", 1156 | "email": "sebastian@phpunit.de" 1157 | } 1158 | ], 1159 | "description": "Provides functionality to handle HHVM/PHP environments", 1160 | "homepage": "http://www.github.com/sebastianbergmann/environment", 1161 | "keywords": [ 1162 | "Xdebug", 1163 | "environment", 1164 | "hhvm" 1165 | ], 1166 | "support": { 1167 | "issues": "https://github.com/sebastianbergmann/environment/issues", 1168 | "source": "https://github.com/sebastianbergmann/environment/tree/4.2.4" 1169 | }, 1170 | "funding": [ 1171 | { 1172 | "url": "https://github.com/sebastianbergmann", 1173 | "type": "github" 1174 | } 1175 | ], 1176 | "time": "2020-11-30T07:53:42+00:00" 1177 | }, 1178 | { 1179 | "name": "sebastian/exporter", 1180 | "version": "3.1.3", 1181 | "source": { 1182 | "type": "git", 1183 | "url": "https://github.com/sebastianbergmann/exporter.git", 1184 | "reference": "6b853149eab67d4da22291d36f5b0631c0fd856e" 1185 | }, 1186 | "dist": { 1187 | "type": "zip", 1188 | "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/6b853149eab67d4da22291d36f5b0631c0fd856e", 1189 | "reference": "6b853149eab67d4da22291d36f5b0631c0fd856e", 1190 | "shasum": "" 1191 | }, 1192 | "require": { 1193 | "php": ">=7.0", 1194 | "sebastian/recursion-context": "^3.0" 1195 | }, 1196 | "require-dev": { 1197 | "ext-mbstring": "*", 1198 | "phpunit/phpunit": "^6.0" 1199 | }, 1200 | "type": "library", 1201 | "extra": { 1202 | "branch-alias": { 1203 | "dev-master": "3.1.x-dev" 1204 | } 1205 | }, 1206 | "autoload": { 1207 | "classmap": [ 1208 | "src/" 1209 | ] 1210 | }, 1211 | "notification-url": "https://packagist.org/downloads/", 1212 | "license": [ 1213 | "BSD-3-Clause" 1214 | ], 1215 | "authors": [ 1216 | { 1217 | "name": "Sebastian Bergmann", 1218 | "email": "sebastian@phpunit.de" 1219 | }, 1220 | { 1221 | "name": "Jeff Welch", 1222 | "email": "whatthejeff@gmail.com" 1223 | }, 1224 | { 1225 | "name": "Volker Dusch", 1226 | "email": "github@wallbash.com" 1227 | }, 1228 | { 1229 | "name": "Adam Harvey", 1230 | "email": "aharvey@php.net" 1231 | }, 1232 | { 1233 | "name": "Bernhard Schussek", 1234 | "email": "bschussek@gmail.com" 1235 | } 1236 | ], 1237 | "description": "Provides the functionality to export PHP variables for visualization", 1238 | "homepage": "http://www.github.com/sebastianbergmann/exporter", 1239 | "keywords": [ 1240 | "export", 1241 | "exporter" 1242 | ], 1243 | "support": { 1244 | "issues": "https://github.com/sebastianbergmann/exporter/issues", 1245 | "source": "https://github.com/sebastianbergmann/exporter/tree/3.1.3" 1246 | }, 1247 | "funding": [ 1248 | { 1249 | "url": "https://github.com/sebastianbergmann", 1250 | "type": "github" 1251 | } 1252 | ], 1253 | "time": "2020-11-30T07:47:53+00:00" 1254 | }, 1255 | { 1256 | "name": "sebastian/global-state", 1257 | "version": "2.0.0", 1258 | "source": { 1259 | "type": "git", 1260 | "url": "https://github.com/sebastianbergmann/global-state.git", 1261 | "reference": "e8ba02eed7bbbb9e59e43dedd3dddeff4a56b0c4" 1262 | }, 1263 | "dist": { 1264 | "type": "zip", 1265 | "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/e8ba02eed7bbbb9e59e43dedd3dddeff4a56b0c4", 1266 | "reference": "e8ba02eed7bbbb9e59e43dedd3dddeff4a56b0c4", 1267 | "shasum": "" 1268 | }, 1269 | "require": { 1270 | "php": "^7.0" 1271 | }, 1272 | "require-dev": { 1273 | "phpunit/phpunit": "^6.0" 1274 | }, 1275 | "suggest": { 1276 | "ext-uopz": "*" 1277 | }, 1278 | "type": "library", 1279 | "extra": { 1280 | "branch-alias": { 1281 | "dev-master": "2.0-dev" 1282 | } 1283 | }, 1284 | "autoload": { 1285 | "classmap": [ 1286 | "src/" 1287 | ] 1288 | }, 1289 | "notification-url": "https://packagist.org/downloads/", 1290 | "license": [ 1291 | "BSD-3-Clause" 1292 | ], 1293 | "authors": [ 1294 | { 1295 | "name": "Sebastian Bergmann", 1296 | "email": "sebastian@phpunit.de" 1297 | } 1298 | ], 1299 | "description": "Snapshotting of global state", 1300 | "homepage": "http://www.github.com/sebastianbergmann/global-state", 1301 | "keywords": [ 1302 | "global state" 1303 | ], 1304 | "support": { 1305 | "issues": "https://github.com/sebastianbergmann/global-state/issues", 1306 | "source": "https://github.com/sebastianbergmann/global-state/tree/2.0.0" 1307 | }, 1308 | "time": "2017-04-27T15:39:26+00:00" 1309 | }, 1310 | { 1311 | "name": "sebastian/object-enumerator", 1312 | "version": "3.0.4", 1313 | "source": { 1314 | "type": "git", 1315 | "url": "https://github.com/sebastianbergmann/object-enumerator.git", 1316 | "reference": "e67f6d32ebd0c749cf9d1dbd9f226c727043cdf2" 1317 | }, 1318 | "dist": { 1319 | "type": "zip", 1320 | "url": "https://api.github.com/repos/sebastianbergmann/object-enumerator/zipball/e67f6d32ebd0c749cf9d1dbd9f226c727043cdf2", 1321 | "reference": "e67f6d32ebd0c749cf9d1dbd9f226c727043cdf2", 1322 | "shasum": "" 1323 | }, 1324 | "require": { 1325 | "php": ">=7.0", 1326 | "sebastian/object-reflector": "^1.1.1", 1327 | "sebastian/recursion-context": "^3.0" 1328 | }, 1329 | "require-dev": { 1330 | "phpunit/phpunit": "^6.0" 1331 | }, 1332 | "type": "library", 1333 | "extra": { 1334 | "branch-alias": { 1335 | "dev-master": "3.0.x-dev" 1336 | } 1337 | }, 1338 | "autoload": { 1339 | "classmap": [ 1340 | "src/" 1341 | ] 1342 | }, 1343 | "notification-url": "https://packagist.org/downloads/", 1344 | "license": [ 1345 | "BSD-3-Clause" 1346 | ], 1347 | "authors": [ 1348 | { 1349 | "name": "Sebastian Bergmann", 1350 | "email": "sebastian@phpunit.de" 1351 | } 1352 | ], 1353 | "description": "Traverses array structures and object graphs to enumerate all referenced objects", 1354 | "homepage": "https://github.com/sebastianbergmann/object-enumerator/", 1355 | "support": { 1356 | "issues": "https://github.com/sebastianbergmann/object-enumerator/issues", 1357 | "source": "https://github.com/sebastianbergmann/object-enumerator/tree/3.0.4" 1358 | }, 1359 | "funding": [ 1360 | { 1361 | "url": "https://github.com/sebastianbergmann", 1362 | "type": "github" 1363 | } 1364 | ], 1365 | "time": "2020-11-30T07:40:27+00:00" 1366 | }, 1367 | { 1368 | "name": "sebastian/object-reflector", 1369 | "version": "1.1.2", 1370 | "source": { 1371 | "type": "git", 1372 | "url": "https://github.com/sebastianbergmann/object-reflector.git", 1373 | "reference": "9b8772b9cbd456ab45d4a598d2dd1a1bced6363d" 1374 | }, 1375 | "dist": { 1376 | "type": "zip", 1377 | "url": "https://api.github.com/repos/sebastianbergmann/object-reflector/zipball/9b8772b9cbd456ab45d4a598d2dd1a1bced6363d", 1378 | "reference": "9b8772b9cbd456ab45d4a598d2dd1a1bced6363d", 1379 | "shasum": "" 1380 | }, 1381 | "require": { 1382 | "php": ">=7.0" 1383 | }, 1384 | "require-dev": { 1385 | "phpunit/phpunit": "^6.0" 1386 | }, 1387 | "type": "library", 1388 | "extra": { 1389 | "branch-alias": { 1390 | "dev-master": "1.1-dev" 1391 | } 1392 | }, 1393 | "autoload": { 1394 | "classmap": [ 1395 | "src/" 1396 | ] 1397 | }, 1398 | "notification-url": "https://packagist.org/downloads/", 1399 | "license": [ 1400 | "BSD-3-Clause" 1401 | ], 1402 | "authors": [ 1403 | { 1404 | "name": "Sebastian Bergmann", 1405 | "email": "sebastian@phpunit.de" 1406 | } 1407 | ], 1408 | "description": "Allows reflection of object attributes, including inherited and non-public ones", 1409 | "homepage": "https://github.com/sebastianbergmann/object-reflector/", 1410 | "support": { 1411 | "issues": "https://github.com/sebastianbergmann/object-reflector/issues", 1412 | "source": "https://github.com/sebastianbergmann/object-reflector/tree/1.1.2" 1413 | }, 1414 | "funding": [ 1415 | { 1416 | "url": "https://github.com/sebastianbergmann", 1417 | "type": "github" 1418 | } 1419 | ], 1420 | "time": "2020-11-30T07:37:18+00:00" 1421 | }, 1422 | { 1423 | "name": "sebastian/recursion-context", 1424 | "version": "3.0.1", 1425 | "source": { 1426 | "type": "git", 1427 | "url": "https://github.com/sebastianbergmann/recursion-context.git", 1428 | "reference": "367dcba38d6e1977be014dc4b22f47a484dac7fb" 1429 | }, 1430 | "dist": { 1431 | "type": "zip", 1432 | "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/367dcba38d6e1977be014dc4b22f47a484dac7fb", 1433 | "reference": "367dcba38d6e1977be014dc4b22f47a484dac7fb", 1434 | "shasum": "" 1435 | }, 1436 | "require": { 1437 | "php": ">=7.0" 1438 | }, 1439 | "require-dev": { 1440 | "phpunit/phpunit": "^6.0" 1441 | }, 1442 | "type": "library", 1443 | "extra": { 1444 | "branch-alias": { 1445 | "dev-master": "3.0.x-dev" 1446 | } 1447 | }, 1448 | "autoload": { 1449 | "classmap": [ 1450 | "src/" 1451 | ] 1452 | }, 1453 | "notification-url": "https://packagist.org/downloads/", 1454 | "license": [ 1455 | "BSD-3-Clause" 1456 | ], 1457 | "authors": [ 1458 | { 1459 | "name": "Sebastian Bergmann", 1460 | "email": "sebastian@phpunit.de" 1461 | }, 1462 | { 1463 | "name": "Jeff Welch", 1464 | "email": "whatthejeff@gmail.com" 1465 | }, 1466 | { 1467 | "name": "Adam Harvey", 1468 | "email": "aharvey@php.net" 1469 | } 1470 | ], 1471 | "description": "Provides functionality to recursively process PHP variables", 1472 | "homepage": "http://www.github.com/sebastianbergmann/recursion-context", 1473 | "support": { 1474 | "issues": "https://github.com/sebastianbergmann/recursion-context/issues", 1475 | "source": "https://github.com/sebastianbergmann/recursion-context/tree/3.0.1" 1476 | }, 1477 | "funding": [ 1478 | { 1479 | "url": "https://github.com/sebastianbergmann", 1480 | "type": "github" 1481 | } 1482 | ], 1483 | "time": "2020-11-30T07:34:24+00:00" 1484 | }, 1485 | { 1486 | "name": "sebastian/resource-operations", 1487 | "version": "2.0.2", 1488 | "source": { 1489 | "type": "git", 1490 | "url": "https://github.com/sebastianbergmann/resource-operations.git", 1491 | "reference": "31d35ca87926450c44eae7e2611d45a7a65ea8b3" 1492 | }, 1493 | "dist": { 1494 | "type": "zip", 1495 | "url": "https://api.github.com/repos/sebastianbergmann/resource-operations/zipball/31d35ca87926450c44eae7e2611d45a7a65ea8b3", 1496 | "reference": "31d35ca87926450c44eae7e2611d45a7a65ea8b3", 1497 | "shasum": "" 1498 | }, 1499 | "require": { 1500 | "php": ">=7.1" 1501 | }, 1502 | "type": "library", 1503 | "extra": { 1504 | "branch-alias": { 1505 | "dev-master": "2.0-dev" 1506 | } 1507 | }, 1508 | "autoload": { 1509 | "classmap": [ 1510 | "src/" 1511 | ] 1512 | }, 1513 | "notification-url": "https://packagist.org/downloads/", 1514 | "license": [ 1515 | "BSD-3-Clause" 1516 | ], 1517 | "authors": [ 1518 | { 1519 | "name": "Sebastian Bergmann", 1520 | "email": "sebastian@phpunit.de" 1521 | } 1522 | ], 1523 | "description": "Provides a list of PHP built-in functions that operate on resources", 1524 | "homepage": "https://www.github.com/sebastianbergmann/resource-operations", 1525 | "support": { 1526 | "issues": "https://github.com/sebastianbergmann/resource-operations/issues", 1527 | "source": "https://github.com/sebastianbergmann/resource-operations/tree/2.0.2" 1528 | }, 1529 | "funding": [ 1530 | { 1531 | "url": "https://github.com/sebastianbergmann", 1532 | "type": "github" 1533 | } 1534 | ], 1535 | "time": "2020-11-30T07:30:19+00:00" 1536 | }, 1537 | { 1538 | "name": "sebastian/version", 1539 | "version": "2.0.1", 1540 | "source": { 1541 | "type": "git", 1542 | "url": "https://github.com/sebastianbergmann/version.git", 1543 | "reference": "99732be0ddb3361e16ad77b68ba41efc8e979019" 1544 | }, 1545 | "dist": { 1546 | "type": "zip", 1547 | "url": "https://api.github.com/repos/sebastianbergmann/version/zipball/99732be0ddb3361e16ad77b68ba41efc8e979019", 1548 | "reference": "99732be0ddb3361e16ad77b68ba41efc8e979019", 1549 | "shasum": "" 1550 | }, 1551 | "require": { 1552 | "php": ">=5.6" 1553 | }, 1554 | "type": "library", 1555 | "extra": { 1556 | "branch-alias": { 1557 | "dev-master": "2.0.x-dev" 1558 | } 1559 | }, 1560 | "autoload": { 1561 | "classmap": [ 1562 | "src/" 1563 | ] 1564 | }, 1565 | "notification-url": "https://packagist.org/downloads/", 1566 | "license": [ 1567 | "BSD-3-Clause" 1568 | ], 1569 | "authors": [ 1570 | { 1571 | "name": "Sebastian Bergmann", 1572 | "email": "sebastian@phpunit.de", 1573 | "role": "lead" 1574 | } 1575 | ], 1576 | "description": "Library that helps with managing the version number of Git-hosted PHP projects", 1577 | "homepage": "https://github.com/sebastianbergmann/version", 1578 | "support": { 1579 | "issues": "https://github.com/sebastianbergmann/version/issues", 1580 | "source": "https://github.com/sebastianbergmann/version/tree/master" 1581 | }, 1582 | "time": "2016-10-03T07:35:21+00:00" 1583 | }, 1584 | { 1585 | "name": "symfony/polyfill-ctype", 1586 | "version": "v1.22.1", 1587 | "source": { 1588 | "type": "git", 1589 | "url": "https://github.com/symfony/polyfill-ctype.git", 1590 | "reference": "c6c942b1ac76c82448322025e084cadc56048b4e" 1591 | }, 1592 | "dist": { 1593 | "type": "zip", 1594 | "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/c6c942b1ac76c82448322025e084cadc56048b4e", 1595 | "reference": "c6c942b1ac76c82448322025e084cadc56048b4e", 1596 | "shasum": "" 1597 | }, 1598 | "require": { 1599 | "php": ">=7.1" 1600 | }, 1601 | "suggest": { 1602 | "ext-ctype": "For best performance" 1603 | }, 1604 | "type": "library", 1605 | "extra": { 1606 | "branch-alias": { 1607 | "dev-main": "1.22-dev" 1608 | }, 1609 | "thanks": { 1610 | "name": "symfony/polyfill", 1611 | "url": "https://github.com/symfony/polyfill" 1612 | } 1613 | }, 1614 | "autoload": { 1615 | "psr-4": { 1616 | "Symfony\\Polyfill\\Ctype\\": "" 1617 | }, 1618 | "files": [ 1619 | "bootstrap.php" 1620 | ] 1621 | }, 1622 | "notification-url": "https://packagist.org/downloads/", 1623 | "license": [ 1624 | "MIT" 1625 | ], 1626 | "authors": [ 1627 | { 1628 | "name": "Gert de Pagter", 1629 | "email": "BackEndTea@gmail.com" 1630 | }, 1631 | { 1632 | "name": "Symfony Community", 1633 | "homepage": "https://symfony.com/contributors" 1634 | } 1635 | ], 1636 | "description": "Symfony polyfill for ctype functions", 1637 | "homepage": "https://symfony.com", 1638 | "keywords": [ 1639 | "compatibility", 1640 | "ctype", 1641 | "polyfill", 1642 | "portable" 1643 | ], 1644 | "support": { 1645 | "source": "https://github.com/symfony/polyfill-ctype/tree/v1.22.1" 1646 | }, 1647 | "funding": [ 1648 | { 1649 | "url": "https://symfony.com/sponsor", 1650 | "type": "custom" 1651 | }, 1652 | { 1653 | "url": "https://github.com/fabpot", 1654 | "type": "github" 1655 | }, 1656 | { 1657 | "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", 1658 | "type": "tidelift" 1659 | } 1660 | ], 1661 | "time": "2021-01-07T16:49:33+00:00" 1662 | }, 1663 | { 1664 | "name": "theseer/tokenizer", 1665 | "version": "1.1.3", 1666 | "source": { 1667 | "type": "git", 1668 | "url": "https://github.com/theseer/tokenizer.git", 1669 | "reference": "11336f6f84e16a720dae9d8e6ed5019efa85a0f9" 1670 | }, 1671 | "dist": { 1672 | "type": "zip", 1673 | "url": "https://api.github.com/repos/theseer/tokenizer/zipball/11336f6f84e16a720dae9d8e6ed5019efa85a0f9", 1674 | "reference": "11336f6f84e16a720dae9d8e6ed5019efa85a0f9", 1675 | "shasum": "" 1676 | }, 1677 | "require": { 1678 | "ext-dom": "*", 1679 | "ext-tokenizer": "*", 1680 | "ext-xmlwriter": "*", 1681 | "php": "^7.0" 1682 | }, 1683 | "type": "library", 1684 | "autoload": { 1685 | "classmap": [ 1686 | "src/" 1687 | ] 1688 | }, 1689 | "notification-url": "https://packagist.org/downloads/", 1690 | "license": [ 1691 | "BSD-3-Clause" 1692 | ], 1693 | "authors": [ 1694 | { 1695 | "name": "Arne Blankerts", 1696 | "email": "arne@blankerts.de", 1697 | "role": "Developer" 1698 | } 1699 | ], 1700 | "description": "A small library for converting tokenized PHP source code into XML and potentially other formats", 1701 | "support": { 1702 | "issues": "https://github.com/theseer/tokenizer/issues", 1703 | "source": "https://github.com/theseer/tokenizer/tree/master" 1704 | }, 1705 | "time": "2019-06-13T22:48:21+00:00" 1706 | }, 1707 | { 1708 | "name": "webmozart/assert", 1709 | "version": "1.9.1", 1710 | "source": { 1711 | "type": "git", 1712 | "url": "https://github.com/webmozarts/assert.git", 1713 | "reference": "bafc69caeb4d49c39fd0779086c03a3738cbb389" 1714 | }, 1715 | "dist": { 1716 | "type": "zip", 1717 | "url": "https://api.github.com/repos/webmozarts/assert/zipball/bafc69caeb4d49c39fd0779086c03a3738cbb389", 1718 | "reference": "bafc69caeb4d49c39fd0779086c03a3738cbb389", 1719 | "shasum": "" 1720 | }, 1721 | "require": { 1722 | "php": "^5.3.3 || ^7.0 || ^8.0", 1723 | "symfony/polyfill-ctype": "^1.8" 1724 | }, 1725 | "conflict": { 1726 | "phpstan/phpstan": "<0.12.20", 1727 | "vimeo/psalm": "<3.9.1" 1728 | }, 1729 | "require-dev": { 1730 | "phpunit/phpunit": "^4.8.36 || ^7.5.13" 1731 | }, 1732 | "type": "library", 1733 | "autoload": { 1734 | "psr-4": { 1735 | "Webmozart\\Assert\\": "src/" 1736 | } 1737 | }, 1738 | "notification-url": "https://packagist.org/downloads/", 1739 | "license": [ 1740 | "MIT" 1741 | ], 1742 | "authors": [ 1743 | { 1744 | "name": "Bernhard Schussek", 1745 | "email": "bschussek@gmail.com" 1746 | } 1747 | ], 1748 | "description": "Assertions to validate method input/output with nice error messages.", 1749 | "keywords": [ 1750 | "assert", 1751 | "check", 1752 | "validate" 1753 | ], 1754 | "support": { 1755 | "issues": "https://github.com/webmozarts/assert/issues", 1756 | "source": "https://github.com/webmozarts/assert/tree/1.9.1" 1757 | }, 1758 | "time": "2020-07-08T17:02:28+00:00" 1759 | } 1760 | ], 1761 | "aliases": [], 1762 | "minimum-stability": "stable", 1763 | "stability-flags": [], 1764 | "prefer-stable": false, 1765 | "prefer-lowest": false, 1766 | "platform": [], 1767 | "platform-dev": [], 1768 | "platform-overrides": { 1769 | "php": "7.1.0" 1770 | }, 1771 | "plugin-api-version": "2.0.0" 1772 | } 1773 | -------------------------------------------------------------------------------- /functions.php: -------------------------------------------------------------------------------- 1 | connect(); 41 | } catch ( Exception $e ) { 42 | 43 | // Predis throws an Exception when it fails a server call. 44 | // To prevent WordPress from fataling, we catch the Exception. 45 | // TODO Perhaps we catch and rethrow? or return instance of 46 | // WP_Error? 47 | throw new Exception( $e->getMessage(), $e->getCode(), $e ); 48 | } 49 | return true; 50 | } 51 | 52 | function build_params( $args ) { 53 | $scheme = 'tcp'; 54 | $hostKey = 'host'; 55 | $isTLS = isset( $args['ssl'] ) && is_array( $args['ssl'] ); 56 | 57 | if ( $isTLS ) { 58 | $scheme = 'tls'; 59 | } elseif ( null === $args['port'] ) { 60 | // If port is null, it's a socket connection 61 | $scheme = 'unix'; 62 | $hostKey = 'path'; 63 | } 64 | 65 | $params = array( 66 | 'scheme' => $scheme, 67 | $hostKey => $args['host'], 68 | ); 69 | 70 | if ( 'unix' !== $scheme ) { 71 | $params['port'] = $args['port']; 72 | } 73 | 74 | if ( $isTLS ) { 75 | $params['ssl'] = $args['ssl']; 76 | } 77 | return $params; 78 | } 79 | 80 | function build_options( $args ) { 81 | 82 | $options = array( 83 | 'exceptions' => true, 84 | 'parameters' => array( 85 | 'password' => isset( $args['auth'] ) ? $args['auth'] : null, 86 | 'database' => isset( $args['database'] ) ? $args['database'] : null, 87 | 'persistent' => isset( $args['persistent'] ) ? $args['persistent'] : null, 88 | ), 89 | ); 90 | 91 | return $options; 92 | } 93 | 94 | function append_error_messages( $errors ) { 95 | return array( 96 | '/^Connection refused/', 97 | ); 98 | } 99 | 100 | function check_client_dependencies_callback() { 101 | return 'WP_Predis\check_client_dependencies'; 102 | } 103 | 104 | function prepare_client_connection_callback() { 105 | return 'WP_Predis\prepare_client_connection'; 106 | } 107 | 108 | function perform_client_connection_callback() { 109 | return 'WP_Predis\perform_client_connection'; 110 | } 111 | 112 | /** 113 | * Shutdown hook. 114 | * 115 | * Runs during shutdown, even if the shutdown happened due 116 | * to a fatal error/exception. 117 | */ 118 | function shutdown() { 119 | global $wp_object_cache; 120 | 121 | // Disconnect a Redis socket if the shutdown happened with a fatal. 122 | // Prevents a persistent socket from being corrupted if the error 123 | // happens while reading from Redis. 124 | 125 | $error = error_get_last(); 126 | if ( $error && $error['type'] === E_ERROR && isset( $wp_object_cache->redis ) ) { 127 | $wp_object_cache->redis->disconnect(); 128 | } 129 | } 130 | -------------------------------------------------------------------------------- /object-cache.php: -------------------------------------------------------------------------------- 1 | 2 | 3 | Sniffs for the coding standards of the WP Redis plugin 4 | 5 | vendor 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | -------------------------------------------------------------------------------- /phpunit.xml: -------------------------------------------------------------------------------- 1 | 9 | 10 | 11 | ./tests/ 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /tests/bootstrap-wp-predis.php: -------------------------------------------------------------------------------- 1 | $v ) { 22 | if ( $v !== $b[ $k ] ) { 23 | return false; 24 | } 25 | } 26 | // we have identical indexes, and no unequal values 27 | return true; 28 | } 29 | -------------------------------------------------------------------------------- /tests/fixtures/phpredis-info.php: -------------------------------------------------------------------------------- 1 | '4.0.1', 5 | 'redis_git_sha1' => 0, 6 | 'redis_git_dirty' => 0, 7 | 'redis_build_id' => 'f37081b32886670b', 8 | 'redis_mode' => 'standalone', 9 | 'os' => 'Darwin 16.7.0 x86_64', 10 | 'arch_bits' => 64, 11 | 'multiplexing_api' => 'kqueue', 12 | 'atomicvar_api' => 'atomic-builtin', 13 | 'gcc_version' => '4.2.1', 14 | 'process_id' => 7830, 15 | 'run_id' => 'ff052fa3c9e7f581ff3b9e0e0f8aafe03fdff8d0', 16 | 'tcp_port' => 6379, 17 | 'uptime_in_seconds' => 163154, 18 | 'uptime_in_days' => 1, 19 | 'hz' => 10, 20 | 'lru_clock' => 9838681, 21 | 'executable' => '/usr/local/opt/redis/bin/redis-server', 22 | 'config_file' => '/usr/local/etc/redis.conf', 23 | 'connected_clients' => 1, 24 | 'client_longest_output_list' => 0, 25 | 'client_biggest_input_buf' => 0, 26 | 'blocked_clients' => 0, 27 | 'used_memory' => 1031072, 28 | 'used_memory_human' => '1006.91K', 29 | 'used_memory_rss' => 1400832, 30 | 'used_memory_rss_human' => '1.34M', 31 | 'used_memory_peak' => 2426048, 32 | 'used_memory_peak_human' => '2.31M', 33 | 'used_memory_peak_perc' => '42.50%', 34 | 'used_memory_overhead' => 1013014, 35 | 'used_memory_startup' => 963312, 36 | 'used_memory_dataset' => 18058, 37 | 'used_memory_dataset_perc' => '26.65%', 38 | 'total_system_memory' => 17179869184, 39 | 'total_system_memory_human' => '16.00G', 40 | 'used_memory_lua' => 37888, 41 | 'used_memory_lua_human' => '37.00K', 42 | 'maxmemory' => 0, 43 | 'maxmemory_human' => '0B', 44 | 'maxmemory_policy' => 'noeviction', 45 | 'mem_fragmentation_ratio' => '1.36', 46 | 'mem_allocator' => 'libc', 47 | 'active_defrag_running' => 0, 48 | 'lazyfree_pending_objects' => 0, 49 | 'loading' => 0, 50 | 'rdb_changes_since_last_save' => 0, 51 | 'rdb_bgsave_in_progress' => 0, 52 | 'rdb_last_save_time' => 1503010591, 53 | 'rdb_last_bgsave_status' => 'ok', 54 | 'rdb_last_bgsave_time_sec' => 0, 55 | 'rdb_current_bgsave_time_sec' => '-1', 56 | 'rdb_last_cow_size' => 0, 57 | 'aof_enabled' => 0, 58 | 'aof_rewrite_in_progress' => 0, 59 | 'aof_rewrite_scheduled' => 0, 60 | 'aof_last_rewrite_time_sec' => '-1', 61 | 'aof_current_rewrite_time_sec' => '-1', 62 | 'aof_last_bgrewrite_status' => 'ok', 63 | 'aof_last_write_status' => 'ok', 64 | 'aof_last_cow_size' => 0, 65 | 'total_connections_received' => 553, 66 | 'total_commands_processed' => 1978, 67 | 'instantaneous_ops_per_sec' => 0, 68 | 'total_net_input_bytes' => 418353, 69 | 'total_net_output_bytes' => 184734, 70 | 'instantaneous_input_kbps' => '0.00', 71 | 'instantaneous_output_kbps' => '0.00', 72 | 'rejected_connections' => 0, 73 | 'sync_full' => 0, 74 | 'sync_partial_ok' => 0, 75 | 'sync_partial_err' => 0, 76 | 'expired_keys' => 4, 77 | 'evicted_keys' => 0, 78 | 'keyspace_hits' => 283, 79 | 'keyspace_misses' => 459, 80 | 'pubsub_channels' => 0, 81 | 'pubsub_patterns' => 0, 82 | 'latest_fork_usec' => 422, 83 | 'migrate_cached_sockets' => 0, 84 | 'slave_expires_tracked_keys' => 0, 85 | 'active_defrag_hits' => 0, 86 | 'active_defrag_misses' => 0, 87 | 'active_defrag_key_hits' => 0, 88 | 'active_defrag_key_misses' => 0, 89 | 'role' => 'master', 90 | 'connected_slaves' => 0, 91 | 'master_replid' => 'f652af702c58e3d2cc4a593149b22931613e2b09', 92 | 'master_replid2' => 0, 93 | 'master_repl_offset' => 0, 94 | 'second_repl_offset' => '-1', 95 | 'repl_backlog_active' => 0, 96 | 'repl_backlog_size' => 1048576, 97 | 'repl_backlog_first_byte_offset' => 0, 98 | 'repl_backlog_histlen' => 0, 99 | 'used_cpu_sys' => '10.92', 100 | 'used_cpu_user' => '6.97', 101 | 'used_cpu_sys_children' => '0.06', 102 | 'used_cpu_user_children' => '0.01', 103 | 'cluster_enabled' => 0, 104 | 'db0' => 'keys=1,expires=0,avg_ttl=0', 105 | ); 106 | -------------------------------------------------------------------------------- /tests/fixtures/predis-info.php: -------------------------------------------------------------------------------- 1 | array( 5 | 'redis_version' => '4.0.1', 6 | 'redis_git_sha1' => '00000000', 7 | 'redis_git_dirty' => '0', 8 | 'redis_build_id' => 'f37081b32886670b', 9 | 'redis_mode' => 'standalone', 10 | 'os' => 'Darwin 16.7.0 x86_64', 11 | 'arch_bits' => '64', 12 | 'multiplexing_api' => 'kqueue', 13 | 'atomicvar_api' => 'atomic-builtin', 14 | 'gcc_version' => '4.2.1', 15 | 'process_id' => '7830', 16 | 'run_id' => 'ff052fa3c9e7f581ff3b9e0e0f8aafe03fdff8d0', 17 | 'tcp_port' => '6379', 18 | 'uptime_in_seconds' => '163207', 19 | 'uptime_in_days' => '1', 20 | 'hz' => '10', 21 | 'lru_clock' => '9838734', 22 | 'executable' => '/usr/local/opt/redis/bin/redis-server', 23 | 'config_file' => '/usr/local/etc/redis.conf', 24 | ), 25 | 'Clients' => array( 26 | 'connected_clients' => '1', 27 | 'client_longest_output_list' => '0', 28 | 'client_biggest_input_buf' => '0', 29 | 'blocked_clients' => '0', 30 | ), 31 | 'Memory' => array( 32 | 'used_memory' => '1031488', 33 | 'used_memory_human' => '1007.31K', 34 | 'used_memory_rss' => '1482752', 35 | 'used_memory_rss_human' => '1.41M', 36 | 'used_memory_peak' => '2426048', 37 | 'used_memory_peak_human' => '2.31M', 38 | 'used_memory_peak_perc' => '42.52%', 39 | 'used_memory_overhead' => '1013014', 40 | 'used_memory_startup' => '963312', 41 | 'used_memory_dataset' => '18474', 42 | 'used_memory_dataset_perc' => '27.10%', 43 | 'total_system_memory' => '17179869184', 44 | 'total_system_memory_human' => '16.00G', 45 | 'used_memory_lua' => '37888', 46 | 'used_memory_lua_human' => '37.00K', 47 | 'maxmemory' => '0', 48 | 'maxmemory_human' => '0B', 49 | 'maxmemory_policy' => 'noeviction', 50 | 'mem_fragmentation_ratio' => '1.44', 51 | 'mem_allocator' => 'libc', 52 | 'active_defrag_running' => '0', 53 | 'lazyfree_pending_objects' => '0', 54 | ), 55 | 'Persistence' => array( 56 | 'loading' => '0', 57 | 'rdb_changes_since_last_save' => '0', 58 | 'rdb_bgsave_in_progress' => '0', 59 | 'rdb_last_save_time' => '1503010591', 60 | 'rdb_last_bgsave_status' => 'ok', 61 | 'rdb_last_bgsave_time_sec' => '0', 62 | 'rdb_current_bgsave_time_sec' => '-1', 63 | 'rdb_last_cow_size' => '0', 64 | 'aof_enabled' => '0', 65 | 'aof_rewrite_in_progress' => '0', 66 | 'aof_rewrite_scheduled' => '0', 67 | 'aof_last_rewrite_time_sec' => '-1', 68 | 'aof_current_rewrite_time_sec' => '-1', 69 | 'aof_last_bgrewrite_status' => 'ok', 70 | 'aof_last_write_status' => 'ok', 71 | 'aof_last_cow_size' => '0', 72 | ), 73 | 'Stats' => array( 74 | 'total_connections_received' => '554', 75 | 'total_commands_processed' => '1980', 76 | 'instantaneous_ops_per_sec' => '0', 77 | 'total_net_input_bytes' => '418381', 78 | 'total_net_output_bytes' => '190194', 79 | 'instantaneous_input_kbps' => '0.00', 80 | 'instantaneous_output_kbps' => '0.00', 81 | 'rejected_connections' => '0', 82 | 'sync_full' => '0', 83 | 'sync_partial_ok' => '0', 84 | 'sync_partial_err' => '0', 85 | 'expired_keys' => '4', 86 | 'evicted_keys' => '0', 87 | 'keyspace_hits' => '283', 88 | 'keyspace_misses' => '459', 89 | 'pubsub_channels' => '0', 90 | 'pubsub_patterns' => '0', 91 | 'latest_fork_usec' => '422', 92 | 'migrate_cached_sockets' => '0', 93 | 'slave_expires_tracked_keys' => '0', 94 | 'active_defrag_hits' => '0', 95 | 'active_defrag_misses' => '0', 96 | 'active_defrag_key_hits' => '0', 97 | 'active_defrag_key_misses' => '0', 98 | ), 99 | 'Replication' => array( 100 | 'role' => 'master', 101 | 'connected_slaves' => '0', 102 | 'master_replid' => 'f652af702c58e3d2cc4a593149b22931613e2b09', 103 | 'master_replid2' => '0000000000000000000000000000000000000000', 104 | 'master_repl_offset' => '0', 105 | 'second_repl_offset' => '-1', 106 | 'repl_backlog_active' => '0', 107 | 'repl_backlog_size' => '1048576', 108 | 'repl_backlog_first_byte_offset' => '0', 109 | 'repl_backlog_histlen' => '0', 110 | ), 111 | 'CPU' => array( 112 | 'used_cpu_sys' => '10.93', 113 | 'used_cpu_user' => '6.98', 114 | 'used_cpu_sys_children' => '0.06', 115 | 'used_cpu_user_children' => '0.01', 116 | ), 117 | 'Cluster' => array( 118 | 'cluster_enabled' => '0', 119 | ), 120 | 'Keyspace' => array( 121 | 'db0' => array( 122 | 'keys' => '1', 123 | 'expires' => '0', 124 | 'avg_ttl' => '0', 125 | ), 126 | ), 127 | ); 128 | -------------------------------------------------------------------------------- /tests/test-functions.php: -------------------------------------------------------------------------------- 1 | '127.0.0.1', 9 | 'port' => 6379, 10 | 'timeout' => 1000, 11 | 'retry_interval' => 100, 12 | ); 13 | 14 | public function test_dependencies() { 15 | $result = WP_Predis\check_client_dependencies(); 16 | if ( class_exists( 'Predis\Client' ) ) { 17 | $this->assertTrue( $result ); 18 | } else { 19 | $this->assertTrue( is_string( $result ) ); 20 | } 21 | } 22 | 23 | public function test_socket_params() { 24 | $socket_path = '/path/to/redis.sock'; 25 | $args = array( 26 | 'host' => $socket_path, 27 | 'port' => null, 28 | ); 29 | $expected = array( 30 | 'scheme' => 'unix', 31 | 'path' => $socket_path, 32 | ); 33 | $actual = WP_Predis\build_params( $args ); 34 | $this->assertTrue( arrays_are_similar( $expected, $actual ) ); 35 | } 36 | 37 | public function test_tls_params() { 38 | $host = '127.0.0.1'; 39 | $ssl = array( 40 | 'cafile' => 'private.pem', 41 | 'verify_peer' => true, 42 | ); 43 | $args = array( 44 | 'host' => $host, 45 | 'port' => 6379, 46 | 'ssl' => $ssl, 47 | ); 48 | $expected = array( 49 | 'scheme' => 'tls', 50 | 'host' => $host, 51 | 'port' => 6379, 52 | 'ssl' => $ssl, 53 | ); 54 | $actual = WP_Predis\build_params( $args ); 55 | $this->assertTrue( arrays_are_similar( $expected, $actual ) ); 56 | } 57 | 58 | public function test_redis_client_connection() { 59 | $redis = WP_Predis\prepare_client_connection( self::$client_parameters ); 60 | $redis->connect(); 61 | $this->assertTrue( $redis->isConnected() ); 62 | } 63 | 64 | public function test_perform_connection() { 65 | $redis = WP_Predis\prepare_client_connection( self::$client_parameters ); 66 | $isSetUp = WP_Predis\perform_client_connection( $redis, array(), array( 67 | // we test the 'exists' function gets called and we pass 68 | // self::$client_parameters['host'] as the argument. We only care 69 | // about if calling 'exists' throws an exception or not 70 | 'exists' => 'host', 71 | ) ); 72 | $this->assertTrue( $isSetUp ); 73 | } 74 | 75 | // we test that 'database' gets passed by setting up 2 connections, one to 76 | // the default and the other to a different database and modifying the same 77 | // key and testing that they're different 78 | public function test_setup_second_database() { 79 | $redis = WP_Predis\prepare_client_connection( self::$client_parameters ); 80 | $second_db = array_merge( self::$client_parameters, array( 81 | 'database' => 2, 82 | ) ); 83 | $redis2 = WP_Predis\prepare_client_connection( $second_db ); 84 | $keys_methods = array( 85 | 'database' => 'select', 86 | ); 87 | WP_Predis\perform_client_connection( $redis, self::$client_parameters, $keys_methods ); 88 | WP_Predis\perform_client_connection( $redis2, $second_db, $keys_methods ); 89 | $redis->set( 'foo', 'bar' ); 90 | $redis2->set( 'foo', 'baz' ); 91 | $this->assertEquals( $redis->get( 'foo' ), 'bar' ); 92 | $this->assertEquals( $redis2->get( 'foo' ), 'baz' ); 93 | $redis->del( 'foo' ); 94 | $redis2->del( 'foo' ); 95 | } 96 | 97 | // we test that auth gets passed by the fact that auth will fail with a bad 98 | // password 99 | public function test_setup_connection_auth() { 100 | $auth = array_merge( self::$client_parameters, array( 101 | 'auth' => 'thiswillfail', 102 | ) ); 103 | $redis = WP_Predis\prepare_client_connection( $auth ); 104 | $keys_methods = array( 105 | 'auth' => 'auth', 106 | ); 107 | $this->expectException( 'Exception' ); 108 | WP_Predis\perform_client_connection( $redis, $auth, $keys_methods ); 109 | } 110 | 111 | public function test_append_error_messages() { 112 | $expected = array( 113 | '/^Connection refused/', 114 | ); 115 | $actual = WP_Predis\append_error_messages(array( 116 | 'error', 117 | )); 118 | $this->assertEquals( $expected, $actual ); 119 | } 120 | 121 | public function test_check_client_dependencies_callback() { 122 | $this->assertEquals( WP_Predis\check_client_dependencies_callback(), 'WP_Predis\check_client_dependencies' ); 123 | } 124 | 125 | public function test_client_connection_callback() { 126 | $this->assertEquals( WP_Predis\prepare_client_connection_callback(), 'WP_Predis\prepare_client_connection' ); 127 | } 128 | 129 | public function test_setup_client_connection_callback() { 130 | $this->assertEquals( WP_Predis\perform_client_connection_callback(), 'WP_Predis\perform_client_connection' ); 131 | } 132 | } 133 | -------------------------------------------------------------------------------- /tests/test-wp-predis-decorator.php: -------------------------------------------------------------------------------- 1 | '127.0.0.1', 9 | 'port' => 6379, 10 | ); 11 | 12 | protected static $options = array(); 13 | 14 | public function setUp() { 15 | parent::setUp(); 16 | $client = new Predis\Client( self::$arguments, self::$options ); 17 | $this->client = new WP_Predis\Decorator( $client ); 18 | } 19 | 20 | public function test_is_connected() { 21 | $this->client->connect(); 22 | $this->assertTrue( $this->client->isConnected() ); 23 | } 24 | 25 | public function test_hexists() { 26 | $key = 'test'; 27 | $field = 'foo'; 28 | 29 | $exists = $this->client->hexists( $key, $field ); 30 | $this->assertFalse( $exists ); 31 | } 32 | 33 | public function test_exists() { 34 | $key = 'test'; 35 | 36 | $exists = $this->client->exists( $key ); 37 | $this->assertFalse( $exists ); 38 | } 39 | 40 | public function test_get() { 41 | $key = 'test'; 42 | 43 | $value = $this->client->get( $key ); 44 | $this->assertFalse( $value ); 45 | } 46 | 47 | public function test_hget() { 48 | $key = 'test'; 49 | $field = 'foo'; 50 | 51 | $value = $this->client->hget( $key, $field ); 52 | $this->assertFalse( $value ); 53 | } 54 | 55 | public function test_setex() { 56 | $key = 'foo'; 57 | $value = 'bar'; 58 | 59 | $result = $this->client->setex( $key, 100, $value ); 60 | $this->assertTrue( $result ); 61 | } 62 | 63 | public function test_set() { 64 | $key = 'foo'; 65 | $value = 'bar'; 66 | 67 | $result = $this->client->set( $key, $value ); 68 | $this->assertTrue( $result ); 69 | } 70 | 71 | public function test_delete() { 72 | $this->client->mset( array( 73 | 'foo' => 'bar', 74 | 'bar' => 'baz', 75 | 'baz' => 'qux', 76 | )); 77 | 78 | $deleted = $this->client->del( 'foo', 'bar', 'baz' ); 79 | $this->assertEquals( 3, $deleted ); 80 | } 81 | 82 | public function test_hdelete() { 83 | $key = 'test'; 84 | $fields = array( 85 | 'foo', 86 | 'bar', 87 | 'baz', 88 | ); 89 | 90 | $this->client->hmset( $key, array( 91 | 'foo' => 'bar', 92 | 'bar' => 'baz', 93 | 'baz' => 'qux', 94 | )); 95 | 96 | $deleted = $this->client->hdel( $key, 'foo', 'bar', 'baz' ); 97 | $this->assertEquals( 3, $deleted ); 98 | } 99 | 100 | public function test_info() { 101 | $phpredis_info = require( dirname( __FILE__ ) . '/fixtures/phpredis-info.php' ); 102 | $predis_info = require( dirname( __FILE__ ) . '/fixtures/predis-info.php' ); 103 | $actual = $this->client->transform_info( $predis_info ); 104 | $this->assertEquals( array_keys( $phpredis_info ), array_keys( $actual ) ); 105 | $this->assertEquals( $phpredis_info['db0'], $actual['db0'] ); 106 | } 107 | 108 | public function test_close() { 109 | $this->assertEquals( null, $this->client->close() ); 110 | } 111 | 112 | public function tearDown() { 113 | parent::tearDown(); 114 | $this->client->flushall(); 115 | } 116 | } 117 | --------------------------------------------------------------------------------