diff --git a/.github/ISSUE_TEMPLATE b/.github/ISSUE_TEMPLATE
index 4bbca121ac..f6706f7401 100644
--- a/.github/ISSUE_TEMPLATE
+++ b/.github/ISSUE_TEMPLATE
@@ -18,6 +18,7 @@ Oh! It's worth noting WP-CLI represents a collection of sub-projects, each with
* `wp core *` https://github.com/wp-cli/core-command
* `wp cron *` https://github.com/wp-cli/cron-command
* `wp db *` https://github.com/wp-cli/db-command
+* `wp embed *` https://github.com/wp-cli/embed-command
* `wp (eval|eval-file)` https://github.com/wp-cli/eval-command
* `wp export` https://github.com/wp-cli/export-command
* `wp (option|post|comment|user|term|site) *` https://github.com/wp-cli/entity-command
diff --git a/.travis.yml b/.travis.yml
index ad37613da4..19a6b056a3 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -7,6 +7,8 @@ php: 7.1
env:
global:
- WP_CLI_BIN_DIR=/tmp/wp-cli-phar
+ - TEST_COMMANDS=0
+ - TEST_COMMANDS_GLOB=*-command
before_script:
- export PATH="$HOME/.composer/vendor/bin:$PATH"
@@ -28,7 +30,7 @@ jobs:
- stage: test
script: ./ci/test.sh
php: 7.0
- env: WP_VERSION=latest
+ env: WP_VERSION=latest WP_CLI_TEST_LOG_RUN_TIMES='stdout,40,40'
- stage: test
script: ./ci/test.sh
php: 5.6
diff --git a/README.md b/README.md
index ccb14cd92b..190592ef2f 100644
--- a/README.md
+++ b/README.md
@@ -7,7 +7,7 @@ Ongoing maintenance is
-The current stable release is [version 1.4.1](https://make.wordpress.org/cli/2017/11/13/version-1-4-1-released/). For announcements, follow [@wpcli on Twitter](https://twitter.com/wpcli) or [sign up for email updates](https://make.wordpress.org/cli/subscribe/). [Check out the roadmap](https://make.wordpress.org/cli/handbook/roadmap/) for an overview of what's planned for upcoming releases.
+The current stable release is [version 1.5.0](https://make.wordpress.org/cli/2018/01/31/version-1-5-0-released/). For announcements, follow [@wpcli on Twitter](https://twitter.com/wpcli) or [sign up for email updates](https://make.wordpress.org/cli/subscribe/). [Check out the roadmap](https://make.wordpress.org/cli/handbook/roadmap/) for an overview of what's planned for upcoming releases.
[](https://travis-ci.org/wp-cli/wp-cli) [](https://gemnasium.com/github.com/wp-cli/wp-cli) [](https://isitmaintained.com/project/wp-cli/wp-cli "Average time to resolve an issue") [](https://isitmaintained.com/project/wp-cli/wp-cli "Percentage of issues still open")
@@ -73,14 +73,17 @@ If WP-CLI was installed successfully, you should see something like this when yo
```bash
$ wp --info
-PHP binary: /usr/bin/php5
-PHP version: 5.5.9-1ubuntu4.14
-php.ini used: /etc/php5/cli/php.ini
+OS: Darwin 16.7.0 Darwin Kernel Version 16.7.0: Thu Jan 11 22:59:40 PST 2018; root:xnu-3789.73.8~1/RELEASE_X86_64 x86_64
+Shell: /bin/zsh
+PHP binary: /usr/local/bin/php
+PHP version: 7.0.22
+php.ini used: /etc/local/etc/php/7.0/php.ini
WP-CLI root dir: /home/wp-cli/.wp-cli
+WP-CLI vendor dir: /home/wp-cli/.wp-cli/vendor
WP-CLI packages dir: /home/wp-cli/.wp-cli/packages/
WP-CLI global config: /home/wp-cli/.wp-cli/config.yml
WP-CLI project config:
-WP-CLI version: 1.4.1
+WP-CLI version: 1.5.0
```
### Updating
diff --git a/VERSION b/VERSION
index 1433486b40..fbffcdf951 100644
--- a/VERSION
+++ b/VERSION
@@ -1 +1 @@
-1.5.0-alpha
+2.0.0-alpha
diff --git a/appveyor.yml b/appveyor.yml
new file mode 100644
index 0000000000..0feddc1501
--- /dev/null
+++ b/appveyor.yml
@@ -0,0 +1,59 @@
+build: off
+clone_folder: c:\projects\wp-cli
+platform: x64
+shallow_clone: true
+skip_tags: true
+version: '{build}'
+
+services:
+ - mysql
+
+branches:
+ only:
+ - github-api
+
+cache:
+ - '%LOCALAPPDATA%\Composer\files'
+ - c:\ProgramData\chocolatey\bin -> appveyor.yml
+ - c:\ProgramData\chocolatey\lib -> appveyor.yml
+ - c:\projects\wp-cli-tools -> appveyor.yml
+
+environment:
+ MYSQL_PWD: Password12!
+
+init:
+ - set PATH=c:\projects\wp-cli-tools;C:\Program Files\Git\bin;C:\cygwin64\bin;C:\Program Files\Java\jdk1.8.0\bin;C:\Program Files\MySQL\MySQL Server 5.7\bin;%PATH%
+ - setx COMPOSER_NO_INTERACTION 1
+ - git config --global core.autocrlf input
+ - ps: Update-AppveyorBuild -Version "$($env:APPVEYOR_REPO_BRANCH) - $($env:APPVEYOR_REPO_COMMIT)"
+
+# BEFORE services are launched.
+install:
+ # Install PHP via WebPI.
+ - cInst webpicommandline -y
+ - WebPICMD /Install /Products:"PHP70" /AcceptEULA
+
+ # Install Composer
+ - ps: mkdir c:\projects\wp-cli-tools -Force
+ - cd c:\projects\wp-cli-tools
+ - ps: Invoke-WebRequest https://getcomposer.org/composer.phar -Outfile composer.phar
+ - ps: Add-Content composer.bat "@php c:\projects\wp-cli-tools\composer.phar %*"
+ - RefreshEnv
+
+ # Install wp-cli dependencies.
+ - cd "%APPVEYOR_BUILD_FOLDER%"
+ - composer install --no-interaction --prefer-source
+
+# AFTER services have been launched.
+before_test:
+ - mysql -e "CREATE DATABASE wp_cli_test charset 'utf8';" --user=root
+ - mysql -e "GRANT ALL PRIVILEGES ON wp_cli_test.* TO wp_cli_test@localhost IDENTIFIED BY 'password1'" --user=root
+ - mysql -e "GRANT ALL PRIVILEGES ON wp_cli_test_scaffold.* TO wp_cli_test@localhost IDENTIFIED BY 'password1'" --user=root
+
+test_script:
+ # Run phpunit.
+ - vendor\bin\phpunit
+ # Run functional tests.
+ - vendor\bin\behat features/validation.feature
+
+on_finish:
diff --git a/bin/wp b/bin/wp
index 053e24227b..5493622ec3 100755
--- a/bin/wp
+++ b/bin/wp
@@ -40,6 +40,11 @@ esac
# Pass in the path to php so that wp-cli knows which one
# to use if it re-launches itself to run other commands.
-export WP_CLI_PHP_USED="$php"
+WP_CLI_PHP_USED="$php"
+case $("$php" -r "echo PHP_OS;") in
+ WINNT*)
+ WP_CLI_PHP_USED="$(cygpath -w -a -- "$WP_CLI_PHP_USED")" ;;
+esac
+export WP_CLI_PHP_USED
exec "$php" $WP_CLI_PHP_ARGS "$SCRIPT_PATH" "$@"
diff --git a/bin/wp.bat b/bin/wp.bat
index 59f953440b..bc21d8113d 100755
--- a/bin/wp.bat
+++ b/bin/wp.bat
@@ -1,2 +1,2 @@
@ECHO OFF
-php "%~dp0../php/boot-fs.php" %*
\ No newline at end of file
+php %WP_CLI_PHP_ARGS% "%~dp0../php/boot-fs.php" %*
diff --git a/ci/test.sh b/ci/test.sh
index a1aba18638..f4bc5ced89 100755
--- a/ci/test.sh
+++ b/ci/test.sh
@@ -7,5 +7,17 @@ phpunit
BEHAT_TAGS=$(php ci/behat-tags.php)
-# Run the functional tests
-vendor/bin/behat --format progress $BEHAT_TAGS --strict
+if [[ $TEST_COMMANDS -eq 0 || $((TEST_COMMANDS & 1)) > 0 ]]; then
+ # Run the functional tests
+ vendor/bin/behat --format progress $BEHAT_TAGS --strict
+fi
+
+if [[ $((TEST_COMMANDS & 2)) > 0 ]]; then
+ # Run the functional tests of commands.
+ TEST_COMMANDS_GLOB=${TEST_COMMANDS_GLOB-*-command}
+ for R in vendor/wp-cli/$TEST_COMMANDS_GLOB; do
+ if [[ -f "$R/behat.yml" ]]; then BEHAT_YML="--config $R/behat.yml"; fi
+ BEHAT_TAGS=$(cd $R && php ../../../ci/behat-tags.php)
+ vendor/bin/behat --format progress $BEHAT_YML $BEHAT_TAGS --strict $R/features
+ done
+fi
diff --git a/composer.json b/composer.json
index 366c303083..2929dfacdb 100644
--- a/composer.json
+++ b/composer.json
@@ -45,6 +45,7 @@
"wp-cli/core-command": "^1.0",
"wp-cli/cron-command": "^1.0",
"wp-cli/db-command": "^1.0",
+ "wp-cli/embed-command": "^1.0",
"wp-cli/entity-command": "^1.0",
"wp-cli/eval-command": "^1.0",
"wp-cli/export-command": "^1.0",
@@ -69,7 +70,6 @@
"dealerdirect/phpcodesniffer-composer-installer": "^0.4.3",
"phpunit/phpunit": "3.7.*",
"roave/security-advisories": "dev-master",
- "wimg/php-compatibility": "^8.0",
"wp-coding-standards/wpcs": "^0.13.1"
},
"suggest": {
@@ -80,6 +80,9 @@
"psr-4": { "": "php/commands/src" }
},
"extra": {
+ "branch-alias": {
+ "dev-master": "1.5.x-dev"
+ },
"autoload-splitter": {
"splitter-logic": "WP_CLI\\AutoloadSplitter",
"splitter-location": "php/WP_CLI/AutoloadSplitter.php",
diff --git a/composer.lock b/composer.lock
deleted file mode 100644
index 50c62cafed..0000000000
--- a/composer.lock
+++ /dev/null
@@ -1,3764 +0,0 @@
-{
- "_readme": [
- "This file locks the dependencies of your project to a known state",
- "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file",
- "This file is @generated automatically"
- ],
- "content-hash": "0dc5e25ccc983dbe1ac137a5638b8654",
- "packages": [
- {
- "name": "composer/ca-bundle",
- "version": "1.1.0",
- "source": {
- "type": "git",
- "url": "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/composer/ca-bundle.git",
- "reference": "943b2c4fcad1ef178d16a713c2468bf7e579c288"
- },
- "dist": {
- "type": "zip",
- "url": "https://api.github.com/repos/composer/ca-bundle/zipball/943b2c4fcad1ef178d16a713c2468bf7e579c288",
- "reference": "943b2c4fcad1ef178d16a713c2468bf7e579c288",
- "shasum": ""
- },
- "require": {
- "ext-openssl": "*",
- "ext-pcre": "*",
- "php": "^5.3.2 || ^7.0"
- },
- "require-dev": {
- "phpunit/phpunit": "^4.8.35",
- "psr/log": "^1.0",
- "symfony/process": "^2.5 || ^3.0 || ^4.0"
- },
- "type": "library",
- "extra": {
- "branch-alias": {
- "dev-master": "1.x-dev"
- }
- },
- "autoload": {
- "psr-4": {
- "Composer\\CaBundle\\": "src"
- }
- },
- "notification-url": "https://packagist.org/downloads/",
- "license": [
- "MIT"
- ],
- "authors": [
- {
- "name": "Jordi Boggiano",
- "email": "j.boggiano@seld.be",
- "homepage": "http://seld.be"
- }
- ],
- "description": "Lets you find a path to the system CA bundle, and includes a fallback to the Mozilla CA bundle.",
- "keywords": [
- "cabundle",
- "cacert",
- "certificate",
- "ssl",
- "tls"
- ],
- "time": "2017-11-29T09:37:33+00:00"
- },
- {
- "name": "composer/composer",
- "version": "1.5.6",
- "source": {
- "type": "git",
- "url": "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/composer/composer.git",
- "reference": "4f7f9c12753ec43f1e4629e2a71cabe81f2a4eab"
- },
- "dist": {
- "type": "zip",
- "url": "https://api.github.com/repos/composer/composer/zipball/4f7f9c12753ec43f1e4629e2a71cabe81f2a4eab",
- "reference": "4f7f9c12753ec43f1e4629e2a71cabe81f2a4eab",
- "shasum": ""
- },
- "require": {
- "composer/ca-bundle": "^1.0",
- "composer/semver": "^1.0",
- "composer/spdx-licenses": "^1.0",
- "justinrainbow/json-schema": "^3.0 || ^4.0 || ^5.0",
- "php": "^5.3.2 || ^7.0",
- "psr/log": "^1.0",
- "seld/cli-prompt": "^1.0",
- "seld/jsonlint": "^1.4",
- "seld/phar-utils": "^1.0",
- "symfony/console": "^2.7 || ^3.0",
- "symfony/filesystem": "^2.7 || ^3.0",
- "symfony/finder": "^2.7 || ^3.0",
- "symfony/process": "^2.7 || ^3.0"
- },
- "require-dev": {
- "phpunit/phpunit": "^4.5 || ^5.0.5",
- "phpunit/phpunit-mock-objects": "^2.3 || ^3.0"
- },
- "suggest": {
- "ext-openssl": "Enabling the openssl extension allows you to access https URLs for repositories and packages",
- "ext-zip": "Enabling the zip extension allows you to unzip archives",
- "ext-zlib": "Allow gzip compression of HTTP requests"
- },
- "bin": [
- "bin/composer"
- ],
- "type": "library",
- "extra": {
- "branch-alias": {
- "dev-master": "1.5-dev"
- }
- },
- "autoload": {
- "psr-4": {
- "Composer\\": "src/Composer"
- }
- },
- "notification-url": "https://packagist.org/downloads/",
- "license": [
- "MIT"
- ],
- "authors": [
- {
- "name": "Nils Adermann",
- "email": "naderman@naderman.de",
- "homepage": "http://www.naderman.de"
- },
- {
- "name": "Jordi Boggiano",
- "email": "j.boggiano@seld.be",
- "homepage": "http://seld.be"
- }
- ],
- "description": "Composer helps you declare, manage and install dependencies of PHP projects, ensuring you have the right stack everywhere.",
- "homepage": "https://getcomposer.org/",
- "keywords": [
- "autoload",
- "dependency",
- "package"
- ],
- "time": "2017-12-18T11:09:18+00:00"
- },
- {
- "name": "composer/semver",
- "version": "1.4.2",
- "source": {
- "type": "git",
- "url": "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/composer/semver.git",
- "reference": "c7cb9a2095a074d131b65a8a0cd294479d785573"
- },
- "dist": {
- "type": "zip",
- "url": "https://api.github.com/repos/composer/semver/zipball/c7cb9a2095a074d131b65a8a0cd294479d785573",
- "reference": "c7cb9a2095a074d131b65a8a0cd294479d785573",
- "shasum": ""
- },
- "require": {
- "php": "^5.3.2 || ^7.0"
- },
- "require-dev": {
- "phpunit/phpunit": "^4.5 || ^5.0.5",
- "phpunit/phpunit-mock-objects": "2.3.0 || ^3.0"
- },
- "type": "library",
- "extra": {
- "branch-alias": {
- "dev-master": "1.x-dev"
- }
- },
- "autoload": {
- "psr-4": {
- "Composer\\Semver\\": "src"
- }
- },
- "notification-url": "https://packagist.org/downloads/",
- "license": [
- "MIT"
- ],
- "authors": [
- {
- "name": "Nils Adermann",
- "email": "naderman@naderman.de",
- "homepage": "http://www.naderman.de"
- },
- {
- "name": "Jordi Boggiano",
- "email": "j.boggiano@seld.be",
- "homepage": "http://seld.be"
- },
- {
- "name": "Rob Bast",
- "email": "rob.bast@gmail.com",
- "homepage": "http://robbast.nl"
- }
- ],
- "description": "Semver library that offers utilities, version constraint parsing and validation.",
- "keywords": [
- "semantic",
- "semver",
- "validation",
- "versioning"
- ],
- "time": "2016-08-30T16:08:34+00:00"
- },
- {
- "name": "composer/spdx-licenses",
- "version": "1.1.6",
- "source": {
- "type": "git",
- "url": "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/composer/spdx-licenses.git",
- "reference": "2603a0d7ddc00a015deb576fa5297ca43dee6b1c"
- },
- "dist": {
- "type": "zip",
- "url": "https://api.github.com/repos/composer/spdx-licenses/zipball/2603a0d7ddc00a015deb576fa5297ca43dee6b1c",
- "reference": "2603a0d7ddc00a015deb576fa5297ca43dee6b1c",
- "shasum": ""
- },
- "require": {
- "php": "^5.3.2 || ^7.0"
- },
- "require-dev": {
- "phpunit/phpunit": "^4.5 || ^5.0.5",
- "phpunit/phpunit-mock-objects": "2.3.0 || ^3.0"
- },
- "type": "library",
- "extra": {
- "branch-alias": {
- "dev-master": "1.x-dev"
- }
- },
- "autoload": {
- "psr-4": {
- "Composer\\Spdx\\": "src"
- }
- },
- "notification-url": "https://packagist.org/downloads/",
- "license": [
- "MIT"
- ],
- "authors": [
- {
- "name": "Nils Adermann",
- "email": "naderman@naderman.de",
- "homepage": "http://www.naderman.de"
- },
- {
- "name": "Jordi Boggiano",
- "email": "j.boggiano@seld.be",
- "homepage": "http://seld.be"
- },
- {
- "name": "Rob Bast",
- "email": "rob.bast@gmail.com",
- "homepage": "http://robbast.nl"
- }
- ],
- "description": "SPDX licenses list and validation library.",
- "keywords": [
- "license",
- "spdx",
- "validator"
- ],
- "time": "2017-04-03T19:08:52+00:00"
- },
- {
- "name": "justinrainbow/json-schema",
- "version": "5.2.6",
- "source": {
- "type": "git",
- "url": "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/justinrainbow/json-schema.git",
- "reference": "d283e11b6e14c6f4664cf080415c4341293e5bbd"
- },
- "dist": {
- "type": "zip",
- "url": "https://api.github.com/repos/justinrainbow/json-schema/zipball/d283e11b6e14c6f4664cf080415c4341293e5bbd",
- "reference": "d283e11b6e14c6f4664cf080415c4341293e5bbd",
- "shasum": ""
- },
- "require": {
- "php": ">=5.3.3"
- },
- "require-dev": {
- "friendsofphp/php-cs-fixer": "^2.1",
- "json-schema/json-schema-test-suite": "1.2.0",
- "phpunit/phpunit": "^4.8.22"
- },
- "bin": [
- "bin/validate-json"
- ],
- "type": "library",
- "extra": {
- "branch-alias": {
- "dev-master": "5.0.x-dev"
- }
- },
- "autoload": {
- "psr-4": {
- "JsonSchema\\": "src/JsonSchema/"
- }
- },
- "notification-url": "https://packagist.org/downloads/",
- "license": [
- "MIT"
- ],
- "authors": [
- {
- "name": "Bruno Prieto Reis",
- "email": "bruno.p.reis@gmail.com"
- },
- {
- "name": "Justin Rainbow",
- "email": "justin.rainbow@gmail.com"
- },
- {
- "name": "Igor Wiedler",
- "email": "igor@wiedler.ch"
- },
- {
- "name": "Robert Schönthal",
- "email": "seroscho@googlemail.com"
- }
- ],
- "description": "A library to validate a json schema.",
- "homepage": "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/justinrainbow/json-schema",
- "keywords": [
- "json",
- "schema"
- ],
- "time": "2017-10-21T13:15:38+00:00"
- },
- {
- "name": "mustache/mustache",
- "version": "v2.12.0",
- "source": {
- "type": "git",
- "url": "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/bobthecow/mustache.php.git",
- "reference": "fe8fe72e9d580591854de404cc59a1b83ca4d19e"
- },
- "dist": {
- "type": "zip",
- "url": "https://api.github.com/repos/bobthecow/mustache.php/zipball/fe8fe72e9d580591854de404cc59a1b83ca4d19e",
- "reference": "fe8fe72e9d580591854de404cc59a1b83ca4d19e",
- "shasum": ""
- },
- "require": {
- "php": ">=5.2.4"
- },
- "require-dev": {
- "friendsofphp/php-cs-fixer": "~1.11",
- "phpunit/phpunit": "~3.7|~4.0|~5.0"
- },
- "type": "library",
- "autoload": {
- "psr-0": {
- "Mustache": "src/"
- }
- },
- "notification-url": "https://packagist.org/downloads/",
- "license": [
- "MIT"
- ],
- "authors": [
- {
- "name": "Justin Hileman",
- "email": "justin@justinhileman.info",
- "homepage": "http://justinhileman.com"
- }
- ],
- "description": "A Mustache implementation in PHP.",
- "homepage": "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/bobthecow/mustache.php",
- "keywords": [
- "mustache",
- "templating"
- ],
- "time": "2017-07-11T12:54:05+00:00"
- },
- {
- "name": "nb/oxymel",
- "version": "v0.1.0",
- "source": {
- "type": "git",
- "url": "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/nb/oxymel.git",
- "reference": "cbe626ef55d5c4cc9b5e6e3904b395861ea76e3c"
- },
- "dist": {
- "type": "zip",
- "url": "https://api.github.com/repos/nb/oxymel/zipball/cbe626ef55d5c4cc9b5e6e3904b395861ea76e3c",
- "reference": "cbe626ef55d5c4cc9b5e6e3904b395861ea76e3c",
- "shasum": ""
- },
- "require": {
- "php": ">=5.2.4"
- },
- "type": "library",
- "autoload": {
- "psr-0": {
- "Oxymel": ""
- }
- },
- "notification-url": "https://packagist.org/downloads/",
- "license": [
- "MIT"
- ],
- "authors": [
- {
- "name": "Nikolay Bachiyski",
- "email": "nb@nikolay.bg",
- "homepage": "http://extrapolate.me/"
- }
- ],
- "description": "A sweet XML builder",
- "homepage": "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/nb/oxymel",
- "keywords": [
- "xml"
- ],
- "time": "2013-02-24T15:01:54+00:00"
- },
- {
- "name": "psr/log",
- "version": "1.0.2",
- "source": {
- "type": "git",
- "url": "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/php-fig/log.git",
- "reference": "4ebe3a8bf773a19edfe0a84b6585ba3d401b724d"
- },
- "dist": {
- "type": "zip",
- "url": "https://api.github.com/repos/php-fig/log/zipball/4ebe3a8bf773a19edfe0a84b6585ba3d401b724d",
- "reference": "4ebe3a8bf773a19edfe0a84b6585ba3d401b724d",
- "shasum": ""
- },
- "require": {
- "php": ">=5.3.0"
- },
- "type": "library",
- "extra": {
- "branch-alias": {
- "dev-master": "1.0.x-dev"
- }
- },
- "autoload": {
- "psr-4": {
- "Psr\\Log\\": "Psr/Log/"
- }
- },
- "notification-url": "https://packagist.org/downloads/",
- "license": [
- "MIT"
- ],
- "authors": [
- {
- "name": "PHP-FIG",
- "homepage": "http://www.php-fig.org/"
- }
- ],
- "description": "Common interface for logging libraries",
- "homepage": "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/php-fig/log",
- "keywords": [
- "log",
- "psr",
- "psr-3"
- ],
- "time": "2016-10-10T12:19:37+00:00"
- },
- {
- "name": "ramsey/array_column",
- "version": "1.1.3",
- "source": {
- "type": "git",
- "url": "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/ramsey/array_column.git",
- "reference": "f8e52eb28e67eb50e613b451dd916abcf783c1db"
- },
- "dist": {
- "type": "zip",
- "url": "https://api.github.com/repos/ramsey/array_column/zipball/f8e52eb28e67eb50e613b451dd916abcf783c1db",
- "reference": "f8e52eb28e67eb50e613b451dd916abcf783c1db",
- "shasum": ""
- },
- "require-dev": {
- "jakub-onderka/php-parallel-lint": "0.8.*",
- "phpunit/phpunit": "~4.5",
- "satooshi/php-coveralls": "0.6.*",
- "squizlabs/php_codesniffer": "~2.2"
- },
- "type": "library",
- "autoload": {
- "files": [
- "src/array_column.php"
- ]
- },
- "notification-url": "https://packagist.org/downloads/",
- "license": [
- "MIT"
- ],
- "authors": [
- {
- "name": "Ben Ramsey",
- "homepage": "http://benramsey.com"
- }
- ],
- "description": "Provides functionality for array_column() to projects using PHP earlier than version 5.5.",
- "homepage": "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/ramsey/array_column",
- "keywords": [
- "array",
- "array_column",
- "column"
- ],
- "time": "2015-03-20T22:07:39+00:00"
- },
- {
- "name": "rmccue/requests",
- "version": "v1.7.0",
- "source": {
- "type": "git",
- "url": "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/rmccue/Requests.git",
- "reference": "87932f52ffad70504d93f04f15690cf16a089546"
- },
- "dist": {
- "type": "zip",
- "url": "https://api.github.com/repos/rmccue/Requests/zipball/87932f52ffad70504d93f04f15690cf16a089546",
- "reference": "87932f52ffad70504d93f04f15690cf16a089546",
- "shasum": ""
- },
- "require": {
- "php": ">=5.2"
- },
- "require-dev": {
- "requests/test-server": "dev-master"
- },
- "type": "library",
- "autoload": {
- "psr-0": {
- "Requests": "library/"
- }
- },
- "notification-url": "https://packagist.org/downloads/",
- "license": [
- "ISC"
- ],
- "authors": [
- {
- "name": "Ryan McCue",
- "homepage": "http://ryanmccue.info"
- }
- ],
- "description": "A HTTP library written in PHP, for human beings.",
- "homepage": "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/rmccue/Requests",
- "keywords": [
- "curl",
- "fsockopen",
- "http",
- "idna",
- "ipv6",
- "iri",
- "sockets"
- ],
- "time": "2016-10-13T00:11:37+00:00"
- },
- {
- "name": "seld/cli-prompt",
- "version": "1.0.3",
- "source": {
- "type": "git",
- "url": "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/Seldaek/cli-prompt.git",
- "reference": "a19a7376a4689d4d94cab66ab4f3c816019ba8dd"
- },
- "dist": {
- "type": "zip",
- "url": "https://api.github.com/repos/Seldaek/cli-prompt/zipball/a19a7376a4689d4d94cab66ab4f3c816019ba8dd",
- "reference": "a19a7376a4689d4d94cab66ab4f3c816019ba8dd",
- "shasum": ""
- },
- "require": {
- "php": ">=5.3"
- },
- "type": "library",
- "extra": {
- "branch-alias": {
- "dev-master": "1.x-dev"
- }
- },
- "autoload": {
- "psr-4": {
- "Seld\\CliPrompt\\": "src/"
- }
- },
- "notification-url": "https://packagist.org/downloads/",
- "license": [
- "MIT"
- ],
- "authors": [
- {
- "name": "Jordi Boggiano",
- "email": "j.boggiano@seld.be"
- }
- ],
- "description": "Allows you to prompt for user input on the command line, and optionally hide the characters they type",
- "keywords": [
- "cli",
- "console",
- "hidden",
- "input",
- "prompt"
- ],
- "time": "2017-03-18T11:32:45+00:00"
- },
- {
- "name": "seld/jsonlint",
- "version": "1.6.2",
- "source": {
- "type": "git",
- "url": "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/Seldaek/jsonlint.git",
- "reference": "7a30649c67ee0d19faacfd9fa2cfb6cc032d9b19"
- },
- "dist": {
- "type": "zip",
- "url": "https://api.github.com/repos/Seldaek/jsonlint/zipball/7a30649c67ee0d19faacfd9fa2cfb6cc032d9b19",
- "reference": "7a30649c67ee0d19faacfd9fa2cfb6cc032d9b19",
- "shasum": ""
- },
- "require": {
- "php": "^5.3 || ^7.0"
- },
- "require-dev": {
- "phpunit/phpunit": "^4.5"
- },
- "bin": [
- "bin/jsonlint"
- ],
- "type": "library",
- "autoload": {
- "psr-4": {
- "Seld\\JsonLint\\": "src/Seld/JsonLint/"
- }
- },
- "notification-url": "https://packagist.org/downloads/",
- "license": [
- "MIT"
- ],
- "authors": [
- {
- "name": "Jordi Boggiano",
- "email": "j.boggiano@seld.be",
- "homepage": "http://seld.be"
- }
- ],
- "description": "JSON Linter",
- "keywords": [
- "json",
- "linter",
- "parser",
- "validator"
- ],
- "time": "2017-11-30T15:34:22+00:00"
- },
- {
- "name": "seld/phar-utils",
- "version": "1.0.1",
- "source": {
- "type": "git",
- "url": "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/Seldaek/phar-utils.git",
- "reference": "7009b5139491975ef6486545a39f3e6dad5ac30a"
- },
- "dist": {
- "type": "zip",
- "url": "https://api.github.com/repos/Seldaek/phar-utils/zipball/7009b5139491975ef6486545a39f3e6dad5ac30a",
- "reference": "7009b5139491975ef6486545a39f3e6dad5ac30a",
- "shasum": ""
- },
- "require": {
- "php": ">=5.3"
- },
- "type": "library",
- "extra": {
- "branch-alias": {
- "dev-master": "1.x-dev"
- }
- },
- "autoload": {
- "psr-4": {
- "Seld\\PharUtils\\": "src/"
- }
- },
- "notification-url": "https://packagist.org/downloads/",
- "license": [
- "MIT"
- ],
- "authors": [
- {
- "name": "Jordi Boggiano",
- "email": "j.boggiano@seld.be"
- }
- ],
- "description": "PHAR file format utilities, for when PHP phars you up",
- "keywords": [
- "phra"
- ],
- "time": "2015-10-13T18:44:15+00:00"
- },
- {
- "name": "symfony/config",
- "version": "v2.8.32",
- "source": {
- "type": "git",
- "url": "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/symfony/config.git",
- "reference": "f4f3f1d7090c464434bbbc3e8aa2b41149c59196"
- },
- "dist": {
- "type": "zip",
- "url": "https://api.github.com/repos/symfony/config/zipball/f4f3f1d7090c464434bbbc3e8aa2b41149c59196",
- "reference": "f4f3f1d7090c464434bbbc3e8aa2b41149c59196",
- "shasum": ""
- },
- "require": {
- "php": ">=5.3.9",
- "symfony/filesystem": "~2.3|~3.0.0"
- },
- "require-dev": {
- "symfony/yaml": "~2.7|~3.0.0"
- },
- "suggest": {
- "symfony/yaml": "To use the yaml reference dumper"
- },
- "type": "library",
- "extra": {
- "branch-alias": {
- "dev-master": "2.8-dev"
- }
- },
- "autoload": {
- "psr-4": {
- "Symfony\\Component\\Config\\": ""
- },
- "exclude-from-classmap": [
- "/Tests/"
- ]
- },
- "notification-url": "https://packagist.org/downloads/",
- "license": [
- "MIT"
- ],
- "authors": [
- {
- "name": "Fabien Potencier",
- "email": "fabien@symfony.com"
- },
- {
- "name": "Symfony Community",
- "homepage": "https://symfony.com/contributors"
- }
- ],
- "description": "Symfony Config Component",
- "homepage": "https://symfony.com",
- "time": "2017-11-07T11:56:23+00:00"
- },
- {
- "name": "symfony/console",
- "version": "v2.8.32",
- "source": {
- "type": "git",
- "url": "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/symfony/console.git",
- "reference": "46270f1ca44f08ebc134ce120fd2c2baf5fd63de"
- },
- "dist": {
- "type": "zip",
- "url": "https://api.github.com/repos/symfony/console/zipball/46270f1ca44f08ebc134ce120fd2c2baf5fd63de",
- "reference": "46270f1ca44f08ebc134ce120fd2c2baf5fd63de",
- "shasum": ""
- },
- "require": {
- "php": ">=5.3.9",
- "symfony/debug": "^2.7.2|~3.0.0",
- "symfony/polyfill-mbstring": "~1.0"
- },
- "require-dev": {
- "psr/log": "~1.0",
- "symfony/event-dispatcher": "~2.1|~3.0.0",
- "symfony/process": "~2.1|~3.0.0"
- },
- "suggest": {
- "psr/log": "For using the console logger",
- "symfony/event-dispatcher": "",
- "symfony/process": ""
- },
- "type": "library",
- "extra": {
- "branch-alias": {
- "dev-master": "2.8-dev"
- }
- },
- "autoload": {
- "psr-4": {
- "Symfony\\Component\\Console\\": ""
- },
- "exclude-from-classmap": [
- "/Tests/"
- ]
- },
- "notification-url": "https://packagist.org/downloads/",
- "license": [
- "MIT"
- ],
- "authors": [
- {
- "name": "Fabien Potencier",
- "email": "fabien@symfony.com"
- },
- {
- "name": "Symfony Community",
- "homepage": "https://symfony.com/contributors"
- }
- ],
- "description": "Symfony Console Component",
- "homepage": "https://symfony.com",
- "time": "2017-11-29T09:33:18+00:00"
- },
- {
- "name": "symfony/debug",
- "version": "v2.8.32",
- "source": {
- "type": "git",
- "url": "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/symfony/debug.git",
- "reference": "e72a0340dc2e273b3c4398d8eef9157ba51d8b95"
- },
- "dist": {
- "type": "zip",
- "url": "https://api.github.com/repos/symfony/debug/zipball/e72a0340dc2e273b3c4398d8eef9157ba51d8b95",
- "reference": "e72a0340dc2e273b3c4398d8eef9157ba51d8b95",
- "shasum": ""
- },
- "require": {
- "php": ">=5.3.9",
- "psr/log": "~1.0"
- },
- "conflict": {
- "symfony/http-kernel": ">=2.3,<2.3.24|~2.4.0|>=2.5,<2.5.9|>=2.6,<2.6.2"
- },
- "require-dev": {
- "symfony/class-loader": "~2.2|~3.0.0",
- "symfony/http-kernel": "~2.3.24|~2.5.9|^2.6.2|~3.0.0"
- },
- "type": "library",
- "extra": {
- "branch-alias": {
- "dev-master": "2.8-dev"
- }
- },
- "autoload": {
- "psr-4": {
- "Symfony\\Component\\Debug\\": ""
- },
- "exclude-from-classmap": [
- "/Tests/"
- ]
- },
- "notification-url": "https://packagist.org/downloads/",
- "license": [
- "MIT"
- ],
- "authors": [
- {
- "name": "Fabien Potencier",
- "email": "fabien@symfony.com"
- },
- {
- "name": "Symfony Community",
- "homepage": "https://symfony.com/contributors"
- }
- ],
- "description": "Symfony Debug Component",
- "homepage": "https://symfony.com",
- "time": "2017-11-19T19:05:05+00:00"
- },
- {
- "name": "symfony/dependency-injection",
- "version": "v2.8.32",
- "source": {
- "type": "git",
- "url": "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/symfony/dependency-injection.git",
- "reference": "d3e81e5402c38500770eb5595d78a6d85ea9e412"
- },
- "dist": {
- "type": "zip",
- "url": "https://api.github.com/repos/symfony/dependency-injection/zipball/d3e81e5402c38500770eb5595d78a6d85ea9e412",
- "reference": "d3e81e5402c38500770eb5595d78a6d85ea9e412",
- "shasum": ""
- },
- "require": {
- "php": ">=5.3.9"
- },
- "conflict": {
- "symfony/expression-language": "<2.6"
- },
- "require-dev": {
- "symfony/config": "~2.2|~3.0.0",
- "symfony/expression-language": "~2.6|~3.0.0",
- "symfony/yaml": "~2.3.42|~2.7.14|~2.8.7|~3.0.7"
- },
- "suggest": {
- "symfony/config": "",
- "symfony/expression-language": "For using expressions in service container configuration",
- "symfony/proxy-manager-bridge": "Generate service proxies to lazy load them",
- "symfony/yaml": ""
- },
- "type": "library",
- "extra": {
- "branch-alias": {
- "dev-master": "2.8-dev"
- }
- },
- "autoload": {
- "psr-4": {
- "Symfony\\Component\\DependencyInjection\\": ""
- },
- "exclude-from-classmap": [
- "/Tests/"
- ]
- },
- "notification-url": "https://packagist.org/downloads/",
- "license": [
- "MIT"
- ],
- "authors": [
- {
- "name": "Fabien Potencier",
- "email": "fabien@symfony.com"
- },
- {
- "name": "Symfony Community",
- "homepage": "https://symfony.com/contributors"
- }
- ],
- "description": "Symfony DependencyInjection Component",
- "homepage": "https://symfony.com",
- "time": "2017-11-23T11:13:33+00:00"
- },
- {
- "name": "symfony/event-dispatcher",
- "version": "v2.8.32",
- "source": {
- "type": "git",
- "url": "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/symfony/event-dispatcher.git",
- "reference": "b59aacf238fadda50d612c9de73b74751872a903"
- },
- "dist": {
- "type": "zip",
- "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/b59aacf238fadda50d612c9de73b74751872a903",
- "reference": "b59aacf238fadda50d612c9de73b74751872a903",
- "shasum": ""
- },
- "require": {
- "php": ">=5.3.9"
- },
- "require-dev": {
- "psr/log": "~1.0",
- "symfony/config": "^2.0.5|~3.0.0",
- "symfony/dependency-injection": "~2.6|~3.0.0",
- "symfony/expression-language": "~2.6|~3.0.0",
- "symfony/stopwatch": "~2.3|~3.0.0"
- },
- "suggest": {
- "symfony/dependency-injection": "",
- "symfony/http-kernel": ""
- },
- "type": "library",
- "extra": {
- "branch-alias": {
- "dev-master": "2.8-dev"
- }
- },
- "autoload": {
- "psr-4": {
- "Symfony\\Component\\EventDispatcher\\": ""
- },
- "exclude-from-classmap": [
- "/Tests/"
- ]
- },
- "notification-url": "https://packagist.org/downloads/",
- "license": [
- "MIT"
- ],
- "authors": [
- {
- "name": "Fabien Potencier",
- "email": "fabien@symfony.com"
- },
- {
- "name": "Symfony Community",
- "homepage": "https://symfony.com/contributors"
- }
- ],
- "description": "Symfony EventDispatcher Component",
- "homepage": "https://symfony.com",
- "time": "2017-11-05T15:25:56+00:00"
- },
- {
- "name": "symfony/filesystem",
- "version": "v2.8.32",
- "source": {
- "type": "git",
- "url": "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/symfony/filesystem.git",
- "reference": "15ceb6736a9eebd0d99f9e05a62296ab6ce1cf2b"
- },
- "dist": {
- "type": "zip",
- "url": "https://api.github.com/repos/symfony/filesystem/zipball/15ceb6736a9eebd0d99f9e05a62296ab6ce1cf2b",
- "reference": "15ceb6736a9eebd0d99f9e05a62296ab6ce1cf2b",
- "shasum": ""
- },
- "require": {
- "php": ">=5.3.9"
- },
- "type": "library",
- "extra": {
- "branch-alias": {
- "dev-master": "2.8-dev"
- }
- },
- "autoload": {
- "psr-4": {
- "Symfony\\Component\\Filesystem\\": ""
- },
- "exclude-from-classmap": [
- "/Tests/"
- ]
- },
- "notification-url": "https://packagist.org/downloads/",
- "license": [
- "MIT"
- ],
- "authors": [
- {
- "name": "Fabien Potencier",
- "email": "fabien@symfony.com"
- },
- {
- "name": "Symfony Community",
- "homepage": "https://symfony.com/contributors"
- }
- ],
- "description": "Symfony Filesystem Component",
- "homepage": "https://symfony.com",
- "time": "2017-11-19T18:39:05+00:00"
- },
- {
- "name": "symfony/finder",
- "version": "v2.8.32",
- "source": {
- "type": "git",
- "url": "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/symfony/finder.git",
- "reference": "efeceae6a05a9b2fcb3391333f1d4a828ff44ab8"
- },
- "dist": {
- "type": "zip",
- "url": "https://api.github.com/repos/symfony/finder/zipball/efeceae6a05a9b2fcb3391333f1d4a828ff44ab8",
- "reference": "efeceae6a05a9b2fcb3391333f1d4a828ff44ab8",
- "shasum": ""
- },
- "require": {
- "php": ">=5.3.9"
- },
- "type": "library",
- "extra": {
- "branch-alias": {
- "dev-master": "2.8-dev"
- }
- },
- "autoload": {
- "psr-4": {
- "Symfony\\Component\\Finder\\": ""
- },
- "exclude-from-classmap": [
- "/Tests/"
- ]
- },
- "notification-url": "https://packagist.org/downloads/",
- "license": [
- "MIT"
- ],
- "authors": [
- {
- "name": "Fabien Potencier",
- "email": "fabien@symfony.com"
- },
- {
- "name": "Symfony Community",
- "homepage": "https://symfony.com/contributors"
- }
- ],
- "description": "Symfony Finder Component",
- "homepage": "https://symfony.com",
- "time": "2017-11-05T15:25:56+00:00"
- },
- {
- "name": "symfony/polyfill-mbstring",
- "version": "v1.6.0",
- "source": {
- "type": "git",
- "url": "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/symfony/polyfill-mbstring.git",
- "reference": "2ec8b39c38cb16674bbf3fea2b6ce5bf117e1296"
- },
- "dist": {
- "type": "zip",
- "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/2ec8b39c38cb16674bbf3fea2b6ce5bf117e1296",
- "reference": "2ec8b39c38cb16674bbf3fea2b6ce5bf117e1296",
- "shasum": ""
- },
- "require": {
- "php": ">=5.3.3"
- },
- "suggest": {
- "ext-mbstring": "For best performance"
- },
- "type": "library",
- "extra": {
- "branch-alias": {
- "dev-master": "1.6-dev"
- }
- },
- "autoload": {
- "psr-4": {
- "Symfony\\Polyfill\\Mbstring\\": ""
- },
- "files": [
- "bootstrap.php"
- ]
- },
- "notification-url": "https://packagist.org/downloads/",
- "license": [
- "MIT"
- ],
- "authors": [
- {
- "name": "Nicolas Grekas",
- "email": "p@tchwork.com"
- },
- {
- "name": "Symfony Community",
- "homepage": "https://symfony.com/contributors"
- }
- ],
- "description": "Symfony polyfill for the Mbstring extension",
- "homepage": "https://symfony.com",
- "keywords": [
- "compatibility",
- "mbstring",
- "polyfill",
- "portable",
- "shim"
- ],
- "time": "2017-10-11T12:05:26+00:00"
- },
- {
- "name": "symfony/process",
- "version": "v2.8.32",
- "source": {
- "type": "git",
- "url": "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/symfony/process.git",
- "reference": "d25449e031f600807949aab7cadbf267712f4eee"
- },
- "dist": {
- "type": "zip",
- "url": "https://api.github.com/repos/symfony/process/zipball/d25449e031f600807949aab7cadbf267712f4eee",
- "reference": "d25449e031f600807949aab7cadbf267712f4eee",
- "shasum": ""
- },
- "require": {
- "php": ">=5.3.9"
- },
- "type": "library",
- "extra": {
- "branch-alias": {
- "dev-master": "2.8-dev"
- }
- },
- "autoload": {
- "psr-4": {
- "Symfony\\Component\\Process\\": ""
- },
- "exclude-from-classmap": [
- "/Tests/"
- ]
- },
- "notification-url": "https://packagist.org/downloads/",
- "license": [
- "MIT"
- ],
- "authors": [
- {
- "name": "Fabien Potencier",
- "email": "fabien@symfony.com"
- },
- {
- "name": "Symfony Community",
- "homepage": "https://symfony.com/contributors"
- }
- ],
- "description": "Symfony Process Component",
- "homepage": "https://symfony.com",
- "time": "2017-11-05T15:25:56+00:00"
- },
- {
- "name": "symfony/translation",
- "version": "v2.8.32",
- "source": {
- "type": "git",
- "url": "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/symfony/translation.git",
- "reference": "0c63d56516c4c4c323228ca6348eadb7c91b1daf"
- },
- "dist": {
- "type": "zip",
- "url": "https://api.github.com/repos/symfony/translation/zipball/0c63d56516c4c4c323228ca6348eadb7c91b1daf",
- "reference": "0c63d56516c4c4c323228ca6348eadb7c91b1daf",
- "shasum": ""
- },
- "require": {
- "php": ">=5.3.9",
- "symfony/polyfill-mbstring": "~1.0"
- },
- "conflict": {
- "symfony/config": "<2.7"
- },
- "require-dev": {
- "psr/log": "~1.0",
- "symfony/config": "~2.8",
- "symfony/intl": "~2.7.25|^2.8.18|~3.2.5",
- "symfony/yaml": "~2.2|~3.0.0"
- },
- "suggest": {
- "psr/log": "To use logging capability in translator",
- "symfony/config": "",
- "symfony/yaml": ""
- },
- "type": "library",
- "extra": {
- "branch-alias": {
- "dev-master": "2.8-dev"
- }
- },
- "autoload": {
- "psr-4": {
- "Symfony\\Component\\Translation\\": ""
- },
- "exclude-from-classmap": [
- "/Tests/"
- ]
- },
- "notification-url": "https://packagist.org/downloads/",
- "license": [
- "MIT"
- ],
- "authors": [
- {
- "name": "Fabien Potencier",
- "email": "fabien@symfony.com"
- },
- {
- "name": "Symfony Community",
- "homepage": "https://symfony.com/contributors"
- }
- ],
- "description": "Symfony Translation Component",
- "homepage": "https://symfony.com",
- "time": "2017-11-07T14:08:47+00:00"
- },
- {
- "name": "symfony/yaml",
- "version": "v2.8.32",
- "source": {
- "type": "git",
- "url": "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/symfony/yaml.git",
- "reference": "968ef42161e4bc04200119da473077f9e7015128"
- },
- "dist": {
- "type": "zip",
- "url": "https://api.github.com/repos/symfony/yaml/zipball/968ef42161e4bc04200119da473077f9e7015128",
- "reference": "968ef42161e4bc04200119da473077f9e7015128",
- "shasum": ""
- },
- "require": {
- "php": ">=5.3.9"
- },
- "type": "library",
- "extra": {
- "branch-alias": {
- "dev-master": "2.8-dev"
- }
- },
- "autoload": {
- "psr-4": {
- "Symfony\\Component\\Yaml\\": ""
- },
- "exclude-from-classmap": [
- "/Tests/"
- ]
- },
- "notification-url": "https://packagist.org/downloads/",
- "license": [
- "MIT"
- ],
- "authors": [
- {
- "name": "Fabien Potencier",
- "email": "fabien@symfony.com"
- },
- {
- "name": "Symfony Community",
- "homepage": "https://symfony.com/contributors"
- }
- ],
- "description": "Symfony Yaml Component",
- "homepage": "https://symfony.com",
- "time": "2017-11-29T09:33:18+00:00"
- },
- {
- "name": "wp-cli/autoload-splitter",
- "version": "v0.1.5",
- "source": {
- "type": "git",
- "url": "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/wp-cli/autoload-splitter.git",
- "reference": "fb4302da26390811d2631c62b42b75976d224bb8"
- },
- "dist": {
- "type": "zip",
- "url": "https://api.github.com/repos/wp-cli/autoload-splitter/zipball/fb4302da26390811d2631c62b42b75976d224bb8",
- "reference": "fb4302da26390811d2631c62b42b75976d224bb8",
- "shasum": ""
- },
- "require": {
- "composer-plugin-api": "^1.1"
- },
- "type": "composer-plugin",
- "extra": {
- "class": "WP_CLI\\AutoloadSplitter\\ComposerPlugin"
- },
- "autoload": {
- "psr-4": {
- "WP_CLI\\AutoloadSplitter\\": "src"
- }
- },
- "notification-url": "https://packagist.org/downloads/",
- "license": [
- "MIT"
- ],
- "authors": [
- {
- "name": "Alain Schlesser",
- "email": "alain.schlesser@gmail.com",
- "homepage": "https://www.alainschlesser.com"
- }
- ],
- "description": "Composer plugin for splitting a generated autoloader into two distinct parts.",
- "homepage": "https://wp-cli.org",
- "time": "2017-08-03T08:40:17+00:00"
- },
- {
- "name": "wp-cli/cache-command",
- "version": "v1.0.6",
- "source": {
- "type": "git",
- "url": "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/wp-cli/cache-command.git",
- "reference": "d82cba9effa198f17847dce5771c8fb20c443ffa"
- },
- "dist": {
- "type": "zip",
- "url": "https://api.github.com/repos/wp-cli/cache-command/zipball/d82cba9effa198f17847dce5771c8fb20c443ffa",
- "reference": "d82cba9effa198f17847dce5771c8fb20c443ffa",
- "shasum": ""
- },
- "require-dev": {
- "behat/behat": "~2.5",
- "wp-cli/wp-cli": "*"
- },
- "type": "wp-cli-package",
- "extra": {
- "branch-alias": {
- "dev-master": "1.x-dev"
- },
- "bundled": true,
- "commands": [
- "cache",
- "cache add",
- "cache decr",
- "cache delete",
- "cache flush",
- "cache get",
- "cache incr",
- "cache replace",
- "cache set",
- "cache type",
- "transient",
- "transient delete",
- "transient get",
- "transient set",
- "transient type"
- ]
- },
- "autoload": {
- "psr-4": {
- "": "src/"
- },
- "files": [
- "cache-command.php"
- ]
- },
- "notification-url": "https://packagist.org/downloads/",
- "license": [
- "MIT"
- ],
- "authors": [
- {
- "name": "Daniel Bachhuber",
- "email": "daniel@runcommand.io",
- "homepage": "https://runcommand.io"
- }
- ],
- "description": "Manages object and transient caches.",
- "homepage": "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/wp-cli/cache-command",
- "time": "2017-12-14T19:21:19+00:00"
- },
- {
- "name": "wp-cli/checksum-command",
- "version": "v1.0.5",
- "source": {
- "type": "git",
- "url": "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/wp-cli/checksum-command.git",
- "reference": "a2719a5ba84ffd7d47511967433da7211e0da55a"
- },
- "dist": {
- "type": "zip",
- "url": "https://api.github.com/repos/wp-cli/checksum-command/zipball/a2719a5ba84ffd7d47511967433da7211e0da55a",
- "reference": "a2719a5ba84ffd7d47511967433da7211e0da55a",
- "shasum": ""
- },
- "require-dev": {
- "behat/behat": "~2.5",
- "wp-cli/wp-cli": "*"
- },
- "type": "wp-cli-package",
- "extra": {
- "branch-alias": {
- "dev-master": "1.x-dev"
- },
- "bundled": true,
- "commands": [
- "checksum core"
- ]
- },
- "autoload": {
- "psr-4": {
- "": "src/"
- },
- "files": [
- "checksum-command.php"
- ]
- },
- "notification-url": "https://packagist.org/downloads/",
- "license": [
- "MIT"
- ],
- "authors": [
- {
- "name": "Daniel Bachhuber",
- "email": "daniel@runcommand.io",
- "homepage": "https://runcommand.io"
- }
- ],
- "description": "Verifies file integrity by comparing to published checksums.",
- "homepage": "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/wp-cli/checksum-command",
- "time": "2017-12-08T15:12:46+00:00"
- },
- {
- "name": "wp-cli/config-command",
- "version": "v1.1.7",
- "source": {
- "type": "git",
- "url": "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/wp-cli/config-command.git",
- "reference": "e0c378457e6eab81ab0cc322aba86afdad57ec45"
- },
- "dist": {
- "type": "zip",
- "url": "https://api.github.com/repos/wp-cli/config-command/zipball/e0c378457e6eab81ab0cc322aba86afdad57ec45",
- "reference": "e0c378457e6eab81ab0cc322aba86afdad57ec45",
- "shasum": ""
- },
- "require-dev": {
- "behat/behat": "~2.5",
- "wp-cli/wp-cli": "*"
- },
- "type": "wp-cli-package",
- "extra": {
- "branch-alias": {
- "dev-master": "1.x-dev"
- },
- "bundled": true,
- "commands": [
- "config",
- "config create",
- "config get",
- "config path"
- ]
- },
- "autoload": {
- "psr-4": {
- "": "src/"
- },
- "files": [
- "config-command.php"
- ]
- },
- "notification-url": "https://packagist.org/downloads/",
- "license": [
- "MIT"
- ],
- "authors": [
- {
- "name": "Daniel Bachhuber",
- "email": "daniel@runcommand.io",
- "homepage": "https://runcommand.io"
- }
- ],
- "description": "Manage the wp-config.php file.",
- "homepage": "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/wp-cli/config-command",
- "time": "2017-12-08T15:12:01+00:00"
- },
- {
- "name": "wp-cli/core-command",
- "version": "v1.0.8",
- "source": {
- "type": "git",
- "url": "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/wp-cli/core-command.git",
- "reference": "b1c3c1bd10d081c24b606fcc6ed89100d59d4218"
- },
- "dist": {
- "type": "zip",
- "url": "https://api.github.com/repos/wp-cli/core-command/zipball/b1c3c1bd10d081c24b606fcc6ed89100d59d4218",
- "reference": "b1c3c1bd10d081c24b606fcc6ed89100d59d4218",
- "shasum": ""
- },
- "require-dev": {
- "behat/behat": "~2.5",
- "wp-cli/wp-cli": "*"
- },
- "type": "wp-cli-package",
- "extra": {
- "branch-alias": {
- "dev-master": "1.x-dev"
- },
- "bundled": true,
- "commands": [
- "core",
- "core check-update",
- "core download",
- "core install",
- "core is-installed",
- "core multisite-convert",
- "core multisite-install",
- "core update",
- "core update-db",
- "core version"
- ]
- },
- "autoload": {
- "psr-4": {
- "": "src/"
- },
- "files": [
- "core-command.php"
- ]
- },
- "notification-url": "https://packagist.org/downloads/",
- "license": [
- "MIT"
- ],
- "authors": [
- {
- "name": "Daniel Bachhuber",
- "email": "daniel@runcommand.io",
- "homepage": "https://runcommand.io"
- }
- ],
- "description": "Downloads, installs, updates, and manages a WordPress installation.",
- "homepage": "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/wp-cli/core-command",
- "time": "2017-12-19T22:21:54+00:00"
- },
- {
- "name": "wp-cli/cron-command",
- "version": "v1.0.5",
- "source": {
- "type": "git",
- "url": "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/wp-cli/cron-command.git",
- "reference": "9da7e36e8f9c14cb171a3c5204cba2865e0ed7ef"
- },
- "dist": {
- "type": "zip",
- "url": "https://api.github.com/repos/wp-cli/cron-command/zipball/9da7e36e8f9c14cb171a3c5204cba2865e0ed7ef",
- "reference": "9da7e36e8f9c14cb171a3c5204cba2865e0ed7ef",
- "shasum": ""
- },
- "require-dev": {
- "behat/behat": "~2.5",
- "wp-cli/wp-cli": "*"
- },
- "type": "wp-cli-package",
- "extra": {
- "branch-alias": {
- "dev-master": "1.x-dev"
- },
- "bundled": true,
- "commands": [
- "cron",
- "cron test",
- "cron event",
- "cron event delete",
- "cron event list",
- "cron event run",
- "cron event schedule",
- "cron schedule",
- "cron schedule list"
- ]
- },
- "autoload": {
- "psr-4": {
- "": "src/"
- },
- "files": [
- "cron-command.php"
- ]
- },
- "notification-url": "https://packagist.org/downloads/",
- "license": [
- "MIT"
- ],
- "authors": [
- {
- "name": "Daniel Bachhuber",
- "email": "daniel@runcommand.io",
- "homepage": "https://runcommand.io"
- }
- ],
- "description": "Tests, runs, and deletes WP-Cron events; manages WP-Cron schedules.",
- "homepage": "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/wp-cli/cron-command",
- "time": "2017-12-08T15:09:54+00:00"
- },
- {
- "name": "wp-cli/db-command",
- "version": "v1.3.2",
- "source": {
- "type": "git",
- "url": "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/wp-cli/db-command.git",
- "reference": "162d72acfd6dc1478e2ef249160bffbfa4293371"
- },
- "dist": {
- "type": "zip",
- "url": "https://api.github.com/repos/wp-cli/db-command/zipball/162d72acfd6dc1478e2ef249160bffbfa4293371",
- "reference": "162d72acfd6dc1478e2ef249160bffbfa4293371",
- "shasum": ""
- },
- "require": {
- "wp-cli/wp-cli": "*"
- },
- "require-dev": {
- "behat/behat": "~2.5"
- },
- "type": "wp-cli-package",
- "extra": {
- "branch-alias": {
- "dev-master": "1.x-dev"
- },
- "bundled": true,
- "commands": [
- "db",
- "db create",
- "db drop",
- "db reset",
- "db check",
- "db optimize",
- "db prefix",
- "db repair",
- "db cli",
- "db query",
- "db export",
- "db import",
- "db search",
- "db tables",
- "db size"
- ]
- },
- "autoload": {
- "psr-4": {
- "": "src/"
- },
- "files": [
- "db-command.php"
- ]
- },
- "notification-url": "https://packagist.org/downloads/",
- "license": [
- "MIT"
- ],
- "authors": [
- {
- "name": "Daniel Bachhuber",
- "email": "daniel@runcommand.io",
- "homepage": "https://runcommand.io"
- }
- ],
- "description": "Performs basic database operations using credentials stored in wp-config.php.",
- "homepage": "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/wp-cli/db-command",
- "time": "2017-12-08T15:04:48+00:00"
- },
- {
- "name": "wp-cli/entity-command",
- "version": "v1.1.4",
- "source": {
- "type": "git",
- "url": "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/wp-cli/entity-command.git",
- "reference": "c3a0c2b478aeb385865e6c406b2ecb1fe1900cb5"
- },
- "dist": {
- "type": "zip",
- "url": "https://api.github.com/repos/wp-cli/entity-command/zipball/c3a0c2b478aeb385865e6c406b2ecb1fe1900cb5",
- "reference": "c3a0c2b478aeb385865e6c406b2ecb1fe1900cb5",
- "shasum": ""
- },
- "require-dev": {
- "behat/behat": "~2.5",
- "phpunit/phpunit": "^4.8",
- "wp-cli/wp-cli": "*"
- },
- "type": "wp-cli-package",
- "extra": {
- "branch-alias": {
- "dev-master": "1.x-dev"
- },
- "bundled": true,
- "commands": [
- "comment",
- "comment approve",
- "comment count",
- "comment create",
- "comment delete",
- "comment exists",
- "comment generate",
- "comment get",
- "comment list",
- "comment meta",
- "comment meta add",
- "comment meta delete",
- "comment meta get",
- "comment meta list",
- "comment meta patch",
- "comment meta pluck",
- "comment meta update",
- "comment recount",
- "comment spam",
- "comment status",
- "comment trash",
- "comment unapprove",
- "comment unspam",
- "comment untrash",
- "comment update",
- "menu",
- "menu create",
- "menu delete",
- "menu item",
- "menu item add-custom",
- "menu item add-post",
- "menu item add-term",
- "menu item delete",
- "menu item list",
- "menu item update",
- "menu list",
- "menu location",
- "menu location assign",
- "menu location list",
- "menu location remove",
- "network meta",
- "network meta add",
- "network meta delete",
- "network meta get",
- "network meta list",
- "network meta patch",
- "network meta pluck",
- "network meta update",
- "option",
- "option add",
- "option delete",
- "option get",
- "option list",
- "option patch",
- "option pluck",
- "option update",
- "post",
- "post create",
- "post delete",
- "post edit",
- "post generate",
- "post get",
- "post list",
- "post meta",
- "post meta add",
- "post meta delete",
- "post meta get",
- "post meta list",
- "post meta patch",
- "post meta pluck",
- "post meta update",
- "post term",
- "post term add",
- "post term list",
- "post term remove",
- "post term set",
- "post update",
- "post-type",
- "post-type get",
- "post-type list",
- "site",
- "site activate",
- "site archive",
- "site create",
- "site deactivate",
- "site delete",
- "site empty",
- "site list",
- "site mature",
- "site option",
- "site private",
- "site public",
- "site spam",
- "site unarchive",
- "site unmature",
- "site unspam",
- "taxonomy",
- "taxonomy get",
- "taxonomy list",
- "term",
- "term create",
- "term delete",
- "term generate",
- "term get",
- "term list",
- "term meta",
- "term meta add",
- "term meta delete",
- "term meta get",
- "term meta list",
- "term meta patch",
- "term meta pluck",
- "term meta update",
- "term recount",
- "term update",
- "user",
- "user add-cap",
- "user add-role",
- "user create",
- "user delete",
- "user generate",
- "user get",
- "user import-csv",
- "user list",
- "user list-caps",
- "user meta",
- "user meta add",
- "user meta delete",
- "user meta get",
- "user meta list",
- "user meta patch",
- "user meta pluck",
- "user meta update",
- "user remove-cap",
- "user remove-role",
- "user session",
- "user session destroy",
- "user session list",
- "user set-role",
- "user spam",
- "user term",
- "user term add",
- "user term list",
- "user term remove",
- "user term set",
- "user unspam",
- "user update"
- ]
- },
- "autoload": {
- "psr-4": {
- "": "src/",
- "WP_CLI\\": "src/WP_CLI"
- },
- "files": [
- "entity-command.php"
- ]
- },
- "notification-url": "https://packagist.org/downloads/",
- "license": [
- "MIT"
- ],
- "authors": [
- {
- "name": "Daniel Bachhuber",
- "email": "daniel@runcommand.io",
- "homepage": "https://runcommand.io"
- }
- ],
- "description": "Manage WordPress core entities.",
- "homepage": "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/wp-cli/entity-command",
- "time": "2017-12-18T20:05:12+00:00"
- },
- {
- "name": "wp-cli/eval-command",
- "version": "v1.0.5",
- "source": {
- "type": "git",
- "url": "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/wp-cli/eval-command.git",
- "reference": "9640d40ab28cd86590396f08f8c382e659f57321"
- },
- "dist": {
- "type": "zip",
- "url": "https://api.github.com/repos/wp-cli/eval-command/zipball/9640d40ab28cd86590396f08f8c382e659f57321",
- "reference": "9640d40ab28cd86590396f08f8c382e659f57321",
- "shasum": ""
- },
- "require": {
- "wp-cli/wp-cli": "*"
- },
- "require-dev": {
- "behat/behat": "~2.5"
- },
- "type": "wp-cli-package",
- "extra": {
- "branch-alias": {
- "dev-master": "1.x-dev"
- },
- "bundled": true,
- "commands": [
- "eval",
- "eval-file"
- ]
- },
- "autoload": {
- "psr-4": {
- "": "src/"
- },
- "files": [
- "eval-command.php"
- ]
- },
- "notification-url": "https://packagist.org/downloads/",
- "license": [
- "MIT"
- ],
- "authors": [
- {
- "name": "Daniel Bachhuber",
- "email": "daniel@runcommand.io",
- "homepage": "https://runcommand.io"
- }
- ],
- "description": "Executes arbitrary PHP code or files.",
- "homepage": "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/wp-cli/eval-command",
- "time": "2017-12-08T14:33:34+00:00"
- },
- {
- "name": "wp-cli/export-command",
- "version": "v1.0.5",
- "source": {
- "type": "git",
- "url": "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/wp-cli/export-command.git",
- "reference": "b8469df00d0e357bbc8a51ffd006ace007449b15"
- },
- "dist": {
- "type": "zip",
- "url": "https://api.github.com/repos/wp-cli/export-command/zipball/b8469df00d0e357bbc8a51ffd006ace007449b15",
- "reference": "b8469df00d0e357bbc8a51ffd006ace007449b15",
- "shasum": ""
- },
- "require": {
- "nb/oxymel": "~0.1.0",
- "wp-cli/wp-cli": "*"
- },
- "require-dev": {
- "behat/behat": "~2.5"
- },
- "type": "wp-cli-package",
- "extra": {
- "branch-alias": {
- "dev-master": "1.x-dev"
- },
- "bundled": true,
- "commands": [
- "export"
- ]
- },
- "autoload": {
- "psr-4": {
- "": "src/"
- },
- "files": [
- "export-command.php"
- ]
- },
- "notification-url": "https://packagist.org/downloads/",
- "license": [
- "MIT"
- ],
- "authors": [
- {
- "name": "Daniel Bachhuber",
- "email": "daniel@runcommand.io",
- "homepage": "https://runcommand.io"
- }
- ],
- "description": "Exports WordPress content to a WXR file.",
- "homepage": "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/wp-cli/export-command",
- "time": "2017-12-14T19:06:14+00:00"
- },
- {
- "name": "wp-cli/extension-command",
- "version": "v1.1.8",
- "source": {
- "type": "git",
- "url": "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/wp-cli/extension-command.git",
- "reference": "7ab2a957383ee63e5082f4854479738c0f2a4474"
- },
- "dist": {
- "type": "zip",
- "url": "https://api.github.com/repos/wp-cli/extension-command/zipball/7ab2a957383ee63e5082f4854479738c0f2a4474",
- "reference": "7ab2a957383ee63e5082f4854479738c0f2a4474",
- "shasum": ""
- },
- "require-dev": {
- "behat/behat": "~2.5",
- "wp-cli/wp-cli": "*"
- },
- "type": "wp-cli-package",
- "extra": {
- "branch-alias": {
- "dev-master": "1.x-dev"
- },
- "bundled": true,
- "commands": [
- "plugin",
- "plugin activate",
- "plugin deactivate",
- "plugin delete",
- "plugin get",
- "plugin install",
- "plugin is-installed",
- "plugin list",
- "plugin path",
- "plugin search",
- "plugin status",
- "plugin toggle",
- "plugin uninstall",
- "plugin update",
- "theme",
- "theme activate",
- "theme delete",
- "theme disable",
- "theme enable",
- "theme get",
- "theme install",
- "theme is-installed",
- "theme list",
- "theme mod",
- "theme mod get",
- "theme mod set",
- "theme mod remove",
- "theme path",
- "theme search",
- "theme status",
- "theme update"
- ]
- },
- "autoload": {
- "psr-4": {
- "": "src/"
- },
- "files": [
- "extension-command.php"
- ]
- },
- "notification-url": "https://packagist.org/downloads/",
- "license": [
- "MIT"
- ],
- "authors": [
- {
- "name": "Daniel Bachhuber",
- "email": "daniel@runcommand.io",
- "homepage": "https://runcommand.io"
- }
- ],
- "description": "Manages plugins and themes, including installs, activations, and updates.",
- "homepage": "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/wp-cli/extension-command",
- "time": "2017-12-08T17:49:39+00:00"
- },
- {
- "name": "wp-cli/import-command",
- "version": "v1.0.6",
- "source": {
- "type": "git",
- "url": "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/wp-cli/import-command.git",
- "reference": "d2c21d590a1bfae6ac4e289a0b57fb1870b5990c"
- },
- "dist": {
- "type": "zip",
- "url": "https://api.github.com/repos/wp-cli/import-command/zipball/d2c21d590a1bfae6ac4e289a0b57fb1870b5990c",
- "reference": "d2c21d590a1bfae6ac4e289a0b57fb1870b5990c",
- "shasum": ""
- },
- "require": {
- "wp-cli/wp-cli": "*"
- },
- "require-dev": {
- "behat/behat": "~2.5"
- },
- "type": "wp-cli-package",
- "extra": {
- "branch-alias": {
- "dev-master": "1.x-dev"
- },
- "bundled": true,
- "commands": [
- "import"
- ]
- },
- "autoload": {
- "psr-4": {
- "": "src/"
- },
- "files": [
- "import-command.php"
- ]
- },
- "notification-url": "https://packagist.org/downloads/",
- "license": [
- "MIT"
- ],
- "authors": [
- {
- "name": "Daniel Bachhuber",
- "email": "daniel@runcommand.io",
- "homepage": "https://runcommand.io"
- }
- ],
- "description": "Imports content from a given WXR file.",
- "homepage": "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/wp-cli/import-command",
- "time": "2017-12-08T15:13:36+00:00"
- },
- {
- "name": "wp-cli/language-command",
- "version": "v1.0.6",
- "source": {
- "type": "git",
- "url": "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/wp-cli/language-command.git",
- "reference": "2a3d1ce5a722a4d70809619a065087aa933f6209"
- },
- "dist": {
- "type": "zip",
- "url": "https://api.github.com/repos/wp-cli/language-command/zipball/2a3d1ce5a722a4d70809619a065087aa933f6209",
- "reference": "2a3d1ce5a722a4d70809619a065087aa933f6209",
- "shasum": ""
- },
- "require-dev": {
- "behat/behat": "~2.5",
- "wp-cli/wp-cli": "*"
- },
- "type": "wp-cli-package",
- "extra": {
- "branch-alias": {
- "dev-master": "1.x-dev"
- },
- "commands": [
- "language",
- "language core",
- "language core activate",
- "language core install",
- "language core list",
- "language core uninstall",
- "language core update"
- ],
- "bundled": true
- },
- "autoload": {
- "psr-4": {
- "": "src/"
- },
- "files": [
- "language-command.php"
- ]
- },
- "notification-url": "https://packagist.org/downloads/",
- "license": [
- "MIT"
- ],
- "authors": [
- {
- "name": "Daniel Bachhuber",
- "email": "daniel@runcommand.io",
- "homepage": "https://runcommand.io"
- }
- ],
- "description": "Installs, activates, and manages language packs.",
- "homepage": "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/wp-cli/language-command",
- "time": "2017-12-08T17:50:26+00:00"
- },
- {
- "name": "wp-cli/media-command",
- "version": "v1.1.3",
- "source": {
- "type": "git",
- "url": "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/wp-cli/media-command.git",
- "reference": "b591fe02ca32f78877300410799a562f7a301d48"
- },
- "dist": {
- "type": "zip",
- "url": "https://api.github.com/repos/wp-cli/media-command/zipball/b591fe02ca32f78877300410799a562f7a301d48",
- "reference": "b591fe02ca32f78877300410799a562f7a301d48",
- "shasum": ""
- },
- "require": {
- "wp-cli/wp-cli": "*"
- },
- "require-dev": {
- "behat/behat": "~2.5"
- },
- "type": "wp-cli-package",
- "extra": {
- "branch-alias": {
- "dev-master": "1.x-dev"
- },
- "commands": [
- "media",
- "media import",
- "media regenerate",
- "media image-size"
- ],
- "bundled": true
- },
- "autoload": {
- "psr-4": {
- "": "src/"
- },
- "files": [
- "media-command.php"
- ]
- },
- "notification-url": "https://packagist.org/downloads/",
- "license": [
- "MIT"
- ],
- "authors": [
- {
- "name": "Daniel Bachhuber",
- "email": "daniel@runcommand.io",
- "homepage": "https://runcommand.io"
- }
- ],
- "description": "Imports files as attachments, regenerates thumbnails, or lists registered image sizes.",
- "homepage": "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/wp-cli/media-command",
- "time": "2017-12-15T15:00:38+00:00"
- },
- {
- "name": "wp-cli/mustangostang-spyc",
- "version": "0.6.3",
- "source": {
- "type": "git",
- "url": "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/wp-cli/spyc.git",
- "reference": "6aa0b4da69ce9e9a2c8402dab8d43cf32c581cc7"
- },
- "dist": {
- "type": "zip",
- "url": "https://api.github.com/repos/wp-cli/spyc/zipball/6aa0b4da69ce9e9a2c8402dab8d43cf32c581cc7",
- "reference": "6aa0b4da69ce9e9a2c8402dab8d43cf32c581cc7",
- "shasum": ""
- },
- "require": {
- "php": ">=5.3.1"
- },
- "require-dev": {
- "phpunit/phpunit": "4.3.*@dev"
- },
- "type": "library",
- "extra": {
- "branch-alias": {
- "dev-master": "0.5.x-dev"
- }
- },
- "autoload": {
- "psr-4": {
- "Mustangostang\\": "src/"
- },
- "files": [
- "includes/functions.php"
- ]
- },
- "notification-url": "https://packagist.org/downloads/",
- "license": [
- "MIT"
- ],
- "authors": [
- {
- "name": "mustangostang",
- "email": "vlad.andersen@gmail.com"
- }
- ],
- "description": "A simple YAML loader/dumper class for PHP (WP-CLI fork)",
- "homepage": "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/mustangostang/spyc/",
- "time": "2017-04-25T11:26:20+00:00"
- },
- {
- "name": "wp-cli/package-command",
- "version": "v1.0.10",
- "source": {
- "type": "git",
- "url": "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/wp-cli/package-command.git",
- "reference": "b7d2ee2fc0f4ff052799fdc4308ac2f99031f66a"
- },
- "dist": {
- "type": "zip",
- "url": "https://api.github.com/repos/wp-cli/package-command/zipball/b7d2ee2fc0f4ff052799fdc4308ac2f99031f66a",
- "reference": "b7d2ee2fc0f4ff052799fdc4308ac2f99031f66a",
- "shasum": ""
- },
- "require": {
- "composer/composer": "^1.2.0",
- "wp-cli/wp-cli": "*"
- },
- "require-dev": {
- "behat/behat": "~2.5"
- },
- "type": "wp-cli-package",
- "extra": {
- "branch-alias": {
- "dev-master": "1.x-dev"
- },
- "commands": [
- "package",
- "package browse",
- "package install",
- "package list",
- "package update",
- "package uninstall"
- ],
- "bundled": true
- },
- "autoload": {
- "psr-4": {
- "": "src/"
- },
- "files": [
- "package-command.php"
- ]
- },
- "notification-url": "https://packagist.org/downloads/",
- "license": [
- "MIT"
- ],
- "authors": [
- {
- "name": "Daniel Bachhuber",
- "email": "daniel@runcommand.io",
- "homepage": "https://runcommand.io"
- }
- ],
- "description": "Lists, installs, and removes WP-CLI packages.",
- "homepage": "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/wp-cli/package-command",
- "time": "2017-12-08T15:46:21+00:00"
- },
- {
- "name": "wp-cli/php-cli-tools",
- "version": "v0.11.8",
- "source": {
- "type": "git",
- "url": "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/wp-cli/php-cli-tools.git",
- "reference": "363c75349f5dde561e0b416dd00f7aaa76fa2c27"
- },
- "dist": {
- "type": "zip",
- "url": "https://api.github.com/repos/wp-cli/php-cli-tools/zipball/363c75349f5dde561e0b416dd00f7aaa76fa2c27",
- "reference": "363c75349f5dde561e0b416dd00f7aaa76fa2c27",
- "shasum": ""
- },
- "require": {
- "php": ">= 5.3.0"
- },
- "type": "library",
- "autoload": {
- "psr-0": {
- "cli": "lib/"
- },
- "files": [
- "lib/cli/cli.php"
- ]
- },
- "notification-url": "https://packagist.org/downloads/",
- "license": [
- "MIT"
- ],
- "authors": [
- {
- "name": "James Logsdon",
- "email": "jlogsdon@php.net",
- "role": "Developer"
- },
- {
- "name": "Daniel Bachhuber",
- "email": "daniel@handbuilt.co",
- "role": "Maintainer"
- }
- ],
- "description": "Console utilities for PHP",
- "homepage": "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/wp-cli/php-cli-tools",
- "keywords": [
- "cli",
- "console"
- ],
- "time": "2017-10-12T21:50:48+00:00"
- },
- {
- "name": "wp-cli/rewrite-command",
- "version": "v1.0.5",
- "source": {
- "type": "git",
- "url": "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/wp-cli/rewrite-command.git",
- "reference": "6b1695887e289ffad14c8f4ea86b5f1d92757408"
- },
- "dist": {
- "type": "zip",
- "url": "https://api.github.com/repos/wp-cli/rewrite-command/zipball/6b1695887e289ffad14c8f4ea86b5f1d92757408",
- "reference": "6b1695887e289ffad14c8f4ea86b5f1d92757408",
- "shasum": ""
- },
- "require-dev": {
- "behat/behat": "~2.5",
- "wp-cli/wp-cli": "*"
- },
- "type": "wp-cli-package",
- "extra": {
- "branch-alias": {
- "dev-master": "1.x-dev"
- },
- "commands": [
- "rewrite",
- "rewrite flush",
- "rewrite list",
- "rewrite structure"
- ],
- "bundled": true
- },
- "autoload": {
- "psr-4": {
- "": "src/"
- },
- "files": [
- "rewrite-command.php"
- ]
- },
- "notification-url": "https://packagist.org/downloads/",
- "license": [
- "MIT"
- ],
- "authors": [
- {
- "name": "Daniel Bachhuber",
- "email": "daniel@runcommand.io",
- "homepage": "https://runcommand.io"
- }
- ],
- "description": "Lists or flushes the site's rewrite rules, updates the permalink structure.",
- "homepage": "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/wp-cli/rewrite-command",
- "time": "2017-12-08T17:51:04+00:00"
- },
- {
- "name": "wp-cli/role-command",
- "version": "v1.0.5",
- "source": {
- "type": "git",
- "url": "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/wp-cli/role-command.git",
- "reference": "be7f8ea91922864d0c75e45953fbe41d44bebb25"
- },
- "dist": {
- "type": "zip",
- "url": "https://api.github.com/repos/wp-cli/role-command/zipball/be7f8ea91922864d0c75e45953fbe41d44bebb25",
- "reference": "be7f8ea91922864d0c75e45953fbe41d44bebb25",
- "shasum": ""
- },
- "require-dev": {
- "behat/behat": "~2.5",
- "wp-cli/wp-cli": "*"
- },
- "type": "wp-cli-package",
- "extra": {
- "branch-alias": {
- "dev-master": "1.x-dev"
- },
- "commands": [
- "role",
- "role create",
- "role delete",
- "role exists",
- "role list",
- "role reset",
- "cap",
- "cap add",
- "cap list",
- "cap remove"
- ],
- "bundled": true
- },
- "autoload": {
- "psr-4": {
- "": "src/"
- },
- "files": [
- "role-command.php"
- ]
- },
- "notification-url": "https://packagist.org/downloads/",
- "license": [
- "MIT"
- ],
- "authors": [
- {
- "name": "Daniel Bachhuber",
- "email": "daniel@runcommand.io",
- "homepage": "https://runcommand.io"
- }
- ],
- "description": "Adds, removes, lists, and resets roles and capabilities.",
- "homepage": "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/wp-cli/role-command",
- "time": "2017-12-08T17:51:40+00:00"
- },
- {
- "name": "wp-cli/scaffold-command",
- "version": "v1.1.1",
- "source": {
- "type": "git",
- "url": "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/wp-cli/scaffold-command.git",
- "reference": "24b4ddeeb9531179921172597064c8f54f9f594d"
- },
- "dist": {
- "type": "zip",
- "url": "https://api.github.com/repos/wp-cli/scaffold-command/zipball/24b4ddeeb9531179921172597064c8f54f9f594d",
- "reference": "24b4ddeeb9531179921172597064c8f54f9f594d",
- "shasum": ""
- },
- "require-dev": {
- "behat/behat": "~2.5",
- "wp-cli/wp-cli": "*"
- },
- "type": "wp-cli-package",
- "extra": {
- "branch-alias": {
- "dev-master": "1.x-dev"
- },
- "commands": [
- "scaffold",
- "scaffold _s",
- "scaffold block",
- "scaffold child-theme",
- "scaffold plugin",
- "scaffold plugin-tests",
- "scaffold post-type",
- "scaffold taxonomy",
- "scaffold theme-tests"
- ],
- "bundled": true
- },
- "autoload": {
- "psr-4": {
- "": "src/"
- },
- "files": [
- "scaffold-command.php"
- ]
- },
- "notification-url": "https://packagist.org/downloads/",
- "license": [
- "MIT"
- ],
- "authors": [
- {
- "name": "Daniel Bachhuber",
- "email": "daniel@runcommand.io",
- "homepage": "https://runcommand.io"
- }
- ],
- "description": "Generates code for post types, taxonomies, blocks, plugins, child themes, etc.",
- "homepage": "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/wp-cli/scaffold-command",
- "time": "2017-12-18T14:24:43+00:00"
- },
- {
- "name": "wp-cli/search-replace-command",
- "version": "v1.1.4",
- "source": {
- "type": "git",
- "url": "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/wp-cli/search-replace-command.git",
- "reference": "813977a75e915581a93f0cb931c325f9a231a2e9"
- },
- "dist": {
- "type": "zip",
- "url": "https://api.github.com/repos/wp-cli/search-replace-command/zipball/813977a75e915581a93f0cb931c325f9a231a2e9",
- "reference": "813977a75e915581a93f0cb931c325f9a231a2e9",
- "shasum": ""
- },
- "require": {
- "wp-cli/wp-cli": "*"
- },
- "require-dev": {
- "behat/behat": "~2.5"
- },
- "type": "wp-cli-package",
- "extra": {
- "branch-alias": {
- "dev-master": "1.x-dev"
- },
- "commands": [
- "search-replace"
- ],
- "bundled": true
- },
- "autoload": {
- "psr-4": {
- "": "src/"
- },
- "files": [
- "search-replace-command.php"
- ]
- },
- "notification-url": "https://packagist.org/downloads/",
- "license": [
- "MIT"
- ],
- "authors": [
- {
- "name": "Daniel Bachhuber",
- "email": "daniel@runcommand.io",
- "homepage": "https://runcommand.io"
- }
- ],
- "description": "Searches/replaces strings in the database.",
- "homepage": "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/wp-cli/search-replace-command",
- "time": "2017-12-11T15:35:16+00:00"
- },
- {
- "name": "wp-cli/server-command",
- "version": "v1.0.9",
- "source": {
- "type": "git",
- "url": "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/wp-cli/server-command.git",
- "reference": "6192e6d7becd07e4c11a8f1560655c73a3b3526a"
- },
- "dist": {
- "type": "zip",
- "url": "https://api.github.com/repos/wp-cli/server-command/zipball/6192e6d7becd07e4c11a8f1560655c73a3b3526a",
- "reference": "6192e6d7becd07e4c11a8f1560655c73a3b3526a",
- "shasum": ""
- },
- "require": {
- "wp-cli/wp-cli": "*"
- },
- "require-dev": {
- "behat/behat": "~2.5"
- },
- "type": "wp-cli-package",
- "extra": {
- "branch-alias": {
- "dev-master": "1.x-dev"
- },
- "commands": [
- "server"
- ],
- "bundled": true
- },
- "autoload": {
- "psr-4": {
- "": "src/"
- },
- "files": [
- "server-command.php"
- ]
- },
- "notification-url": "https://packagist.org/downloads/",
- "license": [
- "MIT"
- ],
- "authors": [
- {
- "name": "Daniel Bachhuber",
- "email": "daniel@runcommand.io",
- "homepage": "https://runcommand.io"
- }
- ],
- "description": "Launches PHP's built-in web server for a specific WordPress installation.",
- "homepage": "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/wp-cli/server-command",
- "time": "2017-12-14T20:06:24+00:00"
- },
- {
- "name": "wp-cli/shell-command",
- "version": "v1.0.5",
- "source": {
- "type": "git",
- "url": "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/wp-cli/shell-command.git",
- "reference": "507603a8994d984b6c4d5bd26e31ede6d9cce37e"
- },
- "dist": {
- "type": "zip",
- "url": "https://api.github.com/repos/wp-cli/shell-command/zipball/507603a8994d984b6c4d5bd26e31ede6d9cce37e",
- "reference": "507603a8994d984b6c4d5bd26e31ede6d9cce37e",
- "shasum": ""
- },
- "require": {
- "wp-cli/wp-cli": "*"
- },
- "require-dev": {
- "behat/behat": "~2.5"
- },
- "type": "wp-cli-package",
- "extra": {
- "branch-alias": {
- "dev-master": "1.x-dev"
- },
- "commands": [
- "shell"
- ],
- "bundled": true
- },
- "autoload": {
- "psr-4": {
- "": "src/",
- "WP_CLI\\": "src/WP_CLI"
- },
- "files": [
- "shell-command.php"
- ]
- },
- "notification-url": "https://packagist.org/downloads/",
- "license": [
- "MIT"
- ],
- "authors": [
- {
- "name": "Daniel Bachhuber",
- "email": "daniel@runcommand.io",
- "homepage": "https://runcommand.io"
- }
- ],
- "description": "Opens an interactive PHP console for running and testing PHP code.",
- "homepage": "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/wp-cli/shell-command",
- "time": "2017-12-08T16:03:53+00:00"
- },
- {
- "name": "wp-cli/super-admin-command",
- "version": "v1.0.6",
- "source": {
- "type": "git",
- "url": "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/wp-cli/super-admin-command.git",
- "reference": "2982d2e6514dbb318561d72d0577746a3a37181e"
- },
- "dist": {
- "type": "zip",
- "url": "https://api.github.com/repos/wp-cli/super-admin-command/zipball/2982d2e6514dbb318561d72d0577746a3a37181e",
- "reference": "2982d2e6514dbb318561d72d0577746a3a37181e",
- "shasum": ""
- },
- "require-dev": {
- "behat/behat": "~2.5",
- "wp-cli/wp-cli": "*"
- },
- "type": "wp-cli-package",
- "extra": {
- "branch-alias": {
- "dev-master": "1.x-dev"
- },
- "commands": [
- "super-admin",
- "super-admin add",
- "super-admin list",
- "super-admin remove"
- ],
- "bundled": true
- },
- "autoload": {
- "psr-4": {
- "": "src/"
- },
- "files": [
- "super-admin-command.php"
- ]
- },
- "notification-url": "https://packagist.org/downloads/",
- "license": [
- "MIT"
- ],
- "authors": [
- {
- "name": "Daniel Bachhuber",
- "email": "daniel@runcommand.io",
- "homepage": "https://runcommand.io"
- }
- ],
- "description": "Lists, adds, or removes super admin users on a multisite installation.",
- "homepage": "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/wp-cli/super-admin-command",
- "time": "2017-12-08T17:43:53+00:00"
- },
- {
- "name": "wp-cli/widget-command",
- "version": "v1.0.5",
- "source": {
- "type": "git",
- "url": "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/wp-cli/widget-command.git",
- "reference": "657e0f77d80c892f8f72f90a3a25112c254386df"
- },
- "dist": {
- "type": "zip",
- "url": "https://api.github.com/repos/wp-cli/widget-command/zipball/657e0f77d80c892f8f72f90a3a25112c254386df",
- "reference": "657e0f77d80c892f8f72f90a3a25112c254386df",
- "shasum": ""
- },
- "require-dev": {
- "behat/behat": "~2.5",
- "wp-cli/wp-cli": "*"
- },
- "type": "wp-cli-package",
- "extra": {
- "branch-alias": {
- "dev-master": "1.x-dev"
- },
- "commands": [
- "widget",
- "widget add",
- "widget deactivate",
- "widget delete",
- "widget list",
- "widget move",
- "widget reset",
- "widget update",
- "sidebar",
- "sidebar list"
- ],
- "bundled": true
- },
- "autoload": {
- "psr-4": {
- "": "src/"
- },
- "files": [
- "widget-command.php"
- ]
- },
- "notification-url": "https://packagist.org/downloads/",
- "license": [
- "MIT"
- ],
- "authors": [
- {
- "name": "Daniel Bachhuber",
- "email": "daniel@runcommand.io",
- "homepage": "https://runcommand.io"
- }
- ],
- "description": "Adds, moves, and removes widgets; lists sidebars.",
- "homepage": "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/wp-cli/widget-command",
- "time": "2017-12-08T17:45:57+00:00"
- }
- ],
- "packages-dev": [
- {
- "name": "behat/behat",
- "version": "v2.5.5",
- "source": {
- "type": "git",
- "url": "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/Behat/Behat.git",
- "reference": "c1e48826b84669c97a1efa78459aedfdcdcf2120"
- },
- "dist": {
- "type": "zip",
- "url": "https://api.github.com/repos/Behat/Behat/zipball/c1e48826b84669c97a1efa78459aedfdcdcf2120",
- "reference": "c1e48826b84669c97a1efa78459aedfdcdcf2120",
- "shasum": ""
- },
- "require": {
- "behat/gherkin": "~2.3.0",
- "php": ">=5.3.1",
- "symfony/config": "~2.3",
- "symfony/console": "~2.0",
- "symfony/dependency-injection": "~2.0",
- "symfony/event-dispatcher": "~2.0",
- "symfony/finder": "~2.0",
- "symfony/translation": "~2.3",
- "symfony/yaml": "~2.0"
- },
- "require-dev": {
- "phpunit/phpunit": "~3.7.19"
- },
- "suggest": {
- "behat/mink-extension": "for integration with Mink testing framework",
- "behat/symfony2-extension": "for integration with Symfony2 web framework",
- "behat/yii-extension": "for integration with Yii web framework"
- },
- "bin": [
- "bin/behat"
- ],
- "type": "library",
- "autoload": {
- "psr-0": {
- "Behat\\Behat": "src/"
- }
- },
- "notification-url": "https://packagist.org/downloads/",
- "license": [
- "MIT"
- ],
- "authors": [
- {
- "name": "Konstantin Kudryashov",
- "email": "ever.zet@gmail.com",
- "homepage": "http://everzet.com"
- }
- ],
- "description": "Scenario-oriented BDD framework for PHP 5.3",
- "homepage": "http://behat.org/",
- "keywords": [
- "BDD",
- "Behat",
- "Symfony2"
- ],
- "time": "2015-06-01T09:37:55+00:00"
- },
- {
- "name": "behat/gherkin",
- "version": "v2.3.5",
- "source": {
- "type": "git",
- "url": "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/Behat/Gherkin.git",
- "reference": "2b33963da5525400573560c173ab5c9c057e1852"
- },
- "dist": {
- "type": "zip",
- "url": "https://api.github.com/repos/Behat/Gherkin/zipball/2b33963da5525400573560c173ab5c9c057e1852",
- "reference": "2b33963da5525400573560c173ab5c9c057e1852",
- "shasum": ""
- },
- "require": {
- "php": ">=5.3.1",
- "symfony/finder": "~2.0"
- },
- "require-dev": {
- "symfony/config": "~2.0",
- "symfony/translation": "~2.0",
- "symfony/yaml": "~2.0"
- },
- "suggest": {
- "symfony/config": "If you want to use Config component to manage resources",
- "symfony/translation": "If you want to use Symfony2 translations adapter",
- "symfony/yaml": "If you want to parse features, represented in YAML files"
- },
- "type": "library",
- "extra": {
- "branch-alias": {
- "dev-develop": "2.2-dev"
- }
- },
- "autoload": {
- "psr-0": {
- "Behat\\Gherkin": "src/"
- }
- },
- "notification-url": "https://packagist.org/downloads/",
- "license": [
- "MIT"
- ],
- "authors": [
- {
- "name": "Konstantin Kudryashov",
- "email": "ever.zet@gmail.com",
- "homepage": "http://everzet.com"
- }
- ],
- "description": "Gherkin DSL parser for PHP 5.3",
- "homepage": "http://behat.org/",
- "keywords": [
- "BDD",
- "Behat",
- "DSL",
- "Symfony2",
- "parser"
- ],
- "time": "2013-10-15T11:22:17+00:00"
- },
- {
- "name": "dealerdirect/phpcodesniffer-composer-installer",
- "version": "v0.4.4",
- "source": {
- "type": "git",
- "url": "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/Dealerdirect/phpcodesniffer-composer-installer.git",
- "reference": "2e41850d5f7797cbb1af7b030d245b3b24e63a08"
- },
- "dist": {
- "type": "zip",
- "url": "https://api.github.com/repos/Dealerdirect/phpcodesniffer-composer-installer/zipball/2e41850d5f7797cbb1af7b030d245b3b24e63a08",
- "reference": "2e41850d5f7797cbb1af7b030d245b3b24e63a08",
- "shasum": ""
- },
- "require": {
- "composer-plugin-api": "^1.0",
- "php": "^5.3|^7",
- "squizlabs/php_codesniffer": "*"
- },
- "require-dev": {
- "composer/composer": "*",
- "wimg/php-compatibility": "^8.0"
- },
- "suggest": {
- "dealerdirect/qa-tools": "All the PHP QA tools you'll need"
- },
- "type": "composer-plugin",
- "extra": {
- "class": "Dealerdirect\\Composer\\Plugin\\Installers\\PHPCodeSniffer\\Plugin"
- },
- "autoload": {
- "psr-4": {
- "Dealerdirect\\Composer\\Plugin\\Installers\\PHPCodeSniffer\\": "src/"
- }
- },
- "notification-url": "https://packagist.org/downloads/",
- "license": [
- "MIT"
- ],
- "authors": [
- {
- "name": "Franck Nijhof",
- "email": "f.nijhof@dealerdirect.nl",
- "homepage": "http://workingatdealerdirect.eu",
- "role": "Developer"
- }
- ],
- "description": "PHP_CodeSniffer Standards Composer Installer Plugin",
- "homepage": "http://workingatdealerdirect.eu",
- "keywords": [
- "PHPCodeSniffer",
- "PHP_CodeSniffer",
- "code quality",
- "codesniffer",
- "composer",
- "installer",
- "phpcs",
- "plugin",
- "qa",
- "quality",
- "standard",
- "standards",
- "style guide",
- "stylecheck",
- "tests"
- ],
- "time": "2017-12-06T16:27:17+00:00"
- },
- {
- "name": "phpunit/php-code-coverage",
- "version": "1.2.18",
- "source": {
- "type": "git",
- "url": "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/sebastianbergmann/php-code-coverage.git",
- "reference": "fe2466802556d3fe4e4d1d58ffd3ccfd0a19be0b"
- },
- "dist": {
- "type": "zip",
- "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/fe2466802556d3fe4e4d1d58ffd3ccfd0a19be0b",
- "reference": "fe2466802556d3fe4e4d1d58ffd3ccfd0a19be0b",
- "shasum": ""
- },
- "require": {
- "php": ">=5.3.3",
- "phpunit/php-file-iterator": ">=1.3.0@stable",
- "phpunit/php-text-template": ">=1.2.0@stable",
- "phpunit/php-token-stream": ">=1.1.3,<1.3.0"
- },
- "require-dev": {
- "phpunit/phpunit": "3.7.*@dev"
- },
- "suggest": {
- "ext-dom": "*",
- "ext-xdebug": ">=2.0.5"
- },
- "type": "library",
- "extra": {
- "branch-alias": {
- "dev-master": "1.2.x-dev"
- }
- },
- "autoload": {
- "classmap": [
- "PHP/"
- ]
- },
- "notification-url": "https://packagist.org/downloads/",
- "include-path": [
- ""
- ],
- "license": [
- "BSD-3-Clause"
- ],
- "authors": [
- {
- "name": "Sebastian Bergmann",
- "email": "sb@sebastian-bergmann.de",
- "role": "lead"
- }
- ],
- "description": "Library that provides collection, processing, and rendering functionality for PHP code coverage information.",
- "homepage": "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/sebastianbergmann/php-code-coverage",
- "keywords": [
- "coverage",
- "testing",
- "xunit"
- ],
- "time": "2014-09-02T10:13:14+00:00"
- },
- {
- "name": "phpunit/php-file-iterator",
- "version": "1.4.5",
- "source": {
- "type": "git",
- "url": "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/sebastianbergmann/php-file-iterator.git",
- "reference": "730b01bc3e867237eaac355e06a36b85dd93a8b4"
- },
- "dist": {
- "type": "zip",
- "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/730b01bc3e867237eaac355e06a36b85dd93a8b4",
- "reference": "730b01bc3e867237eaac355e06a36b85dd93a8b4",
- "shasum": ""
- },
- "require": {
- "php": ">=5.3.3"
- },
- "type": "library",
- "extra": {
- "branch-alias": {
- "dev-master": "1.4.x-dev"
- }
- },
- "autoload": {
- "classmap": [
- "src/"
- ]
- },
- "notification-url": "https://packagist.org/downloads/",
- "license": [
- "BSD-3-Clause"
- ],
- "authors": [
- {
- "name": "Sebastian Bergmann",
- "email": "sb@sebastian-bergmann.de",
- "role": "lead"
- }
- ],
- "description": "FilterIterator implementation that filters files based on a list of suffixes.",
- "homepage": "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/sebastianbergmann/php-file-iterator/",
- "keywords": [
- "filesystem",
- "iterator"
- ],
- "time": "2017-11-27T13:52:08+00:00"
- },
- {
- "name": "phpunit/php-text-template",
- "version": "1.2.1",
- "source": {
- "type": "git",
- "url": "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/sebastianbergmann/php-text-template.git",
- "reference": "31f8b717e51d9a2afca6c9f046f5d69fc27c8686"
- },
- "dist": {
- "type": "zip",
- "url": "https://api.github.com/repos/sebastianbergmann/php-text-template/zipball/31f8b717e51d9a2afca6c9f046f5d69fc27c8686",
- "reference": "31f8b717e51d9a2afca6c9f046f5d69fc27c8686",
- "shasum": ""
- },
- "require": {
- "php": ">=5.3.3"
- },
- "type": "library",
- "autoload": {
- "classmap": [
- "src/"
- ]
- },
- "notification-url": "https://packagist.org/downloads/",
- "license": [
- "BSD-3-Clause"
- ],
- "authors": [
- {
- "name": "Sebastian Bergmann",
- "email": "sebastian@phpunit.de",
- "role": "lead"
- }
- ],
- "description": "Simple template engine.",
- "homepage": "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/sebastianbergmann/php-text-template/",
- "keywords": [
- "template"
- ],
- "time": "2015-06-21T13:50:34+00:00"
- },
- {
- "name": "phpunit/php-timer",
- "version": "1.0.9",
- "source": {
- "type": "git",
- "url": "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/sebastianbergmann/php-timer.git",
- "reference": "3dcf38ca72b158baf0bc245e9184d3fdffa9c46f"
- },
- "dist": {
- "type": "zip",
- "url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/3dcf38ca72b158baf0bc245e9184d3fdffa9c46f",
- "reference": "3dcf38ca72b158baf0bc245e9184d3fdffa9c46f",
- "shasum": ""
- },
- "require": {
- "php": "^5.3.3 || ^7.0"
- },
- "require-dev": {
- "phpunit/phpunit": "^4.8.35 || ^5.7 || ^6.0"
- },
- "type": "library",
- "extra": {
- "branch-alias": {
- "dev-master": "1.0-dev"
- }
- },
- "autoload": {
- "classmap": [
- "src/"
- ]
- },
- "notification-url": "https://packagist.org/downloads/",
- "license": [
- "BSD-3-Clause"
- ],
- "authors": [
- {
- "name": "Sebastian Bergmann",
- "email": "sb@sebastian-bergmann.de",
- "role": "lead"
- }
- ],
- "description": "Utility class for timing",
- "homepage": "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/sebastianbergmann/php-timer/",
- "keywords": [
- "timer"
- ],
- "time": "2017-02-26T11:10:40+00:00"
- },
- {
- "name": "phpunit/php-token-stream",
- "version": "1.2.2",
- "source": {
- "type": "git",
- "url": "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/sebastianbergmann/php-token-stream.git",
- "reference": "ad4e1e23ae01b483c16f600ff1bebec184588e32"
- },
- "dist": {
- "type": "zip",
- "url": "https://api.github.com/repos/sebastianbergmann/php-token-stream/zipball/ad4e1e23ae01b483c16f600ff1bebec184588e32",
- "reference": "ad4e1e23ae01b483c16f600ff1bebec184588e32",
- "shasum": ""
- },
- "require": {
- "ext-tokenizer": "*",
- "php": ">=5.3.3"
- },
- "type": "library",
- "extra": {
- "branch-alias": {
- "dev-master": "1.2-dev"
- }
- },
- "autoload": {
- "classmap": [
- "PHP/"
- ]
- },
- "notification-url": "https://packagist.org/downloads/",
- "include-path": [
- ""
- ],
- "license": [
- "BSD-3-Clause"
- ],
- "authors": [
- {
- "name": "Sebastian Bergmann",
- "email": "sb@sebastian-bergmann.de",
- "role": "lead"
- }
- ],
- "description": "Wrapper around PHP's tokenizer extension.",
- "homepage": "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/sebastianbergmann/php-token-stream/",
- "keywords": [
- "tokenizer"
- ],
- "time": "2014-03-03T05:10:30+00:00"
- },
- {
- "name": "phpunit/phpunit",
- "version": "3.7.38",
- "source": {
- "type": "git",
- "url": "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/sebastianbergmann/phpunit.git",
- "reference": "38709dc22d519a3d1be46849868aa2ddf822bcf6"
- },
- "dist": {
- "type": "zip",
- "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/38709dc22d519a3d1be46849868aa2ddf822bcf6",
- "reference": "38709dc22d519a3d1be46849868aa2ddf822bcf6",
- "shasum": ""
- },
- "require": {
- "ext-ctype": "*",
- "ext-dom": "*",
- "ext-json": "*",
- "ext-pcre": "*",
- "ext-reflection": "*",
- "ext-spl": "*",
- "php": ">=5.3.3",
- "phpunit/php-code-coverage": "~1.2",
- "phpunit/php-file-iterator": "~1.3",
- "phpunit/php-text-template": "~1.1",
- "phpunit/php-timer": "~1.0",
- "phpunit/phpunit-mock-objects": "~1.2",
- "symfony/yaml": "~2.0"
- },
- "require-dev": {
- "pear-pear.php.net/pear": "1.9.4"
- },
- "suggest": {
- "phpunit/php-invoker": "~1.1"
- },
- "bin": [
- "composer/bin/phpunit"
- ],
- "type": "library",
- "extra": {
- "branch-alias": {
- "dev-master": "3.7.x-dev"
- }
- },
- "autoload": {
- "classmap": [
- "PHPUnit/"
- ]
- },
- "notification-url": "https://packagist.org/downloads/",
- "include-path": [
- "",
- "../../symfony/yaml/"
- ],
- "license": [
- "BSD-3-Clause"
- ],
- "authors": [
- {
- "name": "Sebastian Bergmann",
- "email": "sebastian@phpunit.de",
- "role": "lead"
- }
- ],
- "description": "The PHP Unit Testing framework.",
- "homepage": "http://www.phpunit.de/",
- "keywords": [
- "phpunit",
- "testing",
- "xunit"
- ],
- "time": "2014-10-17T09:04:17+00:00"
- },
- {
- "name": "phpunit/phpunit-mock-objects",
- "version": "1.2.3",
- "source": {
- "type": "git",
- "url": "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/sebastianbergmann/phpunit-mock-objects.git",
- "reference": "5794e3c5c5ba0fb037b11d8151add2a07fa82875"
- },
- "dist": {
- "type": "zip",
- "url": "https://api.github.com/repos/sebastianbergmann/phpunit-mock-objects/zipball/5794e3c5c5ba0fb037b11d8151add2a07fa82875",
- "reference": "5794e3c5c5ba0fb037b11d8151add2a07fa82875",
- "shasum": ""
- },
- "require": {
- "php": ">=5.3.3",
- "phpunit/php-text-template": ">=1.1.1@stable"
- },
- "suggest": {
- "ext-soap": "*"
- },
- "type": "library",
- "autoload": {
- "classmap": [
- "PHPUnit/"
- ]
- },
- "notification-url": "https://packagist.org/downloads/",
- "include-path": [
- ""
- ],
- "license": [
- "BSD-3-Clause"
- ],
- "authors": [
- {
- "name": "Sebastian Bergmann",
- "email": "sb@sebastian-bergmann.de",
- "role": "lead"
- }
- ],
- "description": "Mock Object library for PHPUnit",
- "homepage": "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/sebastianbergmann/phpunit-mock-objects/",
- "keywords": [
- "mock",
- "xunit"
- ],
- "time": "2013-01-13T10:24:48+00:00"
- },
- {
- "name": "roave/security-advisories",
- "version": "dev-master",
- "source": {
- "type": "git",
- "url": "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/Roave/SecurityAdvisories.git",
- "reference": "0703d860f83775029738dc4a519301e8e3d81853"
- },
- "dist": {
- "type": "zip",
- "url": "https://api.github.com/repos/Roave/SecurityAdvisories/zipball/0703d860f83775029738dc4a519301e8e3d81853",
- "reference": "0703d860f83775029738dc4a519301e8e3d81853",
- "shasum": ""
- },
- "conflict": {
- "adodb/adodb-php": "<5.20.6",
- "amphp/artax": "<1.0.6|>=2,<2.0.6",
- "aws/aws-sdk-php": ">=3,<3.2.1",
- "bugsnag/bugsnag-laravel": ">=2,<2.0.2",
- "cakephp/cakephp": ">=1.3,<1.3.18|>=2,<2.4.99|>=2.5,<2.5.99|>=2.6,<2.6.12|>=2.7,<2.7.6|>=3,<3.0.15|>=3.1,<3.1.4",
- "cart2quote/module-quotation": ">=4.1.6,<=4.4.5|>=5,<5.4.4",
- "cartalyst/sentry": "<=2.1.6",
- "codeigniter/framework": "<=3.0.6",
- "composer/composer": "<=1.0.0-alpha11",
- "contao-components/mediaelement": ">=2.14.2,<2.21.1",
- "contao/core": ">=2,<3.5.31",
- "contao/core-bundle": ">=4,<4.4.8",
- "contao/listing-bundle": ">=4,<4.4.8",
- "doctrine/annotations": ">=1,<1.2.7",
- "doctrine/cache": ">=1,<1.3.2|>=1.4,<1.4.2",
- "doctrine/common": ">=2,<2.4.3|>=2.5,<2.5.1",
- "doctrine/dbal": ">=2,<2.0.8|>=2.1,<2.1.2",
- "doctrine/doctrine-bundle": "<1.5.2",
- "doctrine/doctrine-module": "<=0.7.1",
- "doctrine/mongodb-odm": ">=1,<1.0.2",
- "doctrine/mongodb-odm-bundle": ">=2,<3.0.1",
- "doctrine/orm": ">=2,<2.4.8|>=2.5,<2.5.1",
- "dompdf/dompdf": ">=0.6,<0.6.2",
- "drupal/core": ">=8,<8.3.7",
- "drupal/drupal": ">=8,<8.3.7",
- "ezsystems/ezpublish-legacy": ">=5.3,<5.3.12.2|>=5.4,<5.4.10.1|>=2017.8,<2017.8.1.1",
- "firebase/php-jwt": "<2",
- "friendsofsymfony/rest-bundle": ">=1.2,<1.2.2",
- "friendsofsymfony/user-bundle": ">=1.2,<1.3.5",
- "gree/jose": "<=2.2",
- "gregwar/rst": "<1.0.3",
- "guzzlehttp/guzzle": ">=6,<6.2.1|>=4.0.0-rc2,<4.2.4|>=5,<5.3.1",
- "illuminate/auth": ">=4,<4.0.99|>=4.1,<4.1.26",
- "illuminate/database": ">=4,<4.0.99|>=4.1,<4.1.29",
- "joomla/session": "<1.3.1",
- "laravel/framework": ">=4,<4.0.99|>=4.1,<4.1.29",
- "laravel/socialite": ">=1,<1.0.99|>=2,<2.0.10",
- "magento/magento1ce": ">=1.5.0.1,<1.9.3.2",
- "magento/magento1ee": ">=1.9,<1.14.3.2",
- "magento/magento2ce": ">=2,<2.2",
- "monolog/monolog": ">=1.8,<1.12",
- "namshi/jose": "<2.2",
- "onelogin/php-saml": "<2.10.4",
- "oro/crm": ">=1.7,<1.7.4",
- "oro/platform": ">=1.7,<1.7.4",
- "phpmailer/phpmailer": ">=5,<5.2.24",
- "phpunit/phpunit": ">=4.8.19,<4.8.28|>=5.0.10,<5.6.3",
- "phpxmlrpc/extras": "<6.0.1",
- "pusher/pusher-php-server": "<2.2.1",
- "sabre/dav": ">=1.6,<1.6.99|>=1.7,<1.7.11|>=1.8,<1.8.9",
- "shopware/shopware": "<5.2.25",
- "silverstripe/cms": ">=3,<=3.0.11|>=3.1,<3.1.11",
- "silverstripe/forum": "<=0.6.1|>=0.7,<=0.7.3",
- "silverstripe/framework": ">=3,<3.3",
- "silverstripe/userforms": "<3",
- "simplesamlphp/saml2": "<1.8.1|>=1.9,<1.9.1|>=1.10,<1.10.3|>=2,<2.3.3",
- "simplesamlphp/simplesamlphp": "<1.14.16",
- "simplesamlphp/simplesamlphp-module-infocard": "<1.0.1",
- "socalnick/scn-social-auth": "<1.15.2",
- "squizlabs/php_codesniffer": ">=1,<2.8.1",
- "swiftmailer/swiftmailer": ">=4,<5.4.5",
- "symfony/dependency-injection": ">=2,<2.0.17",
- "symfony/form": ">=2.3,<2.3.35|>=2.4,<2.6.12|>=2.7,<2.7.38|>=2.8,<2.8.31|>=3,<3.2.14|>=3.3,<3.3.13",
- "symfony/framework-bundle": ">=2,<2.3.18|>=2.4,<2.4.8|>=2.5,<2.5.2",
- "symfony/http-foundation": ">=2,<2.3.27|>=2.4,<2.5.11|>=2.6,<2.6.6",
- "symfony/http-kernel": ">=2,<2.3.29|>=2.4,<2.5.12|>=2.6,<2.6.8",
- "symfony/intl": ">=2.7,<2.7.38|>=2.8,<2.8.31|>=3,<3.2.14|>=3.3,<3.3.13",
- "symfony/routing": ">=2,<2.0.19",
- "symfony/security": ">=2,<2.0.25|>=2.1,<2.1.13|>=2.2,<2.2.9|>=2.3,<2.3.37|>=2.4,<2.6.13|>=2.7,<2.7.9|>=2.7.30,<2.7.32|>=2.8.23,<2.8.25|>=3.2.10,<3.2.12|>=3.3.3,<3.3.5",
- "symfony/security-core": ">=2.4,<2.6.13|>=2.7,<2.7.9|>=2.7.30,<2.7.32|>=2.8,<2.8.6|>=2.8.23,<2.8.25|>=3,<3.0.6|>=3.2.10,<3.2.12|>=3.3.3,<3.3.5",
- "symfony/security-csrf": ">=2.7,<2.7.38|>=2.8,<2.8.31|>=3,<3.2.14|>=3.3,<3.3.13",
- "symfony/security-http": ">=2.3,<2.3.41|>=2.4,<2.7.38|>=2.8,<2.8.31|>=3,<3.2.14|>=3.3,<3.3.13",
- "symfony/serializer": ">=2,<2.0.11",
- "symfony/symfony": ">=2,<2.3.41|>=2.4,<2.7.38|>=2.8,<2.8.31|>=3,<3.2.14|>=3.3,<3.3.13",
- "symfony/translation": ">=2,<2.0.17",
- "symfony/validator": ">=2,<2.0.24|>=2.1,<2.1.12|>=2.2,<2.2.5|>=2.3,<2.3.3",
- "symfony/web-profiler-bundle": ">=2,<2.3.19|>=2.4,<2.4.9|>=2.5,<2.5.4",
- "symfony/yaml": ">=2,<2.0.22|>=2.1,<2.1.7",
- "thelia/backoffice-default-template": ">=2.1,<2.1.2",
- "thelia/thelia": ">=2.1.0-beta1,<2.1.3|>=2.1,<2.1.2",
- "twig/twig": "<1.20",
- "typo3/cms": ">=6.2,<6.2.30|>=7,<7.6.22|>=8,<8.7.5",
- "typo3/flow": ">=1,<1.0.4|>=1.1,<1.1.1|>=2,<2.0.1|>=2.3,<2.3.16|>=3,<3.0.10|>=3.1,<3.1.7|>=3.2,<3.2.7|>=3.3,<3.3.5",
- "typo3/neos": ">=1.1,<1.1.3|>=1.2,<1.2.13|>=2,<2.0.4",
- "willdurand/js-translation-bundle": "<2.1.1",
- "yiisoft/yii": ">=1.1.14,<1.1.15",
- "yiisoft/yii2": "<2.0.5",
- "yiisoft/yii2-bootstrap": "<2.0.4",
- "yiisoft/yii2-dev": "<2.0.4",
- "yiisoft/yii2-gii": "<2.0.4",
- "yiisoft/yii2-jui": "<2.0.4",
- "zendframework/zend-cache": ">=2.4,<2.4.8|>=2.5,<2.5.3",
- "zendframework/zend-captcha": ">=2,<2.4.9|>=2.5,<2.5.2",
- "zendframework/zend-crypt": ">=2,<2.4.9|>=2.5,<2.5.2",
- "zendframework/zend-db": ">=2,<2.0.99|>=2.1,<2.1.99|>=2.2,<2.2.10|>=2.3,<2.3.5",
- "zendframework/zend-diactoros": ">=1,<1.0.4",
- "zendframework/zend-form": ">=2,<2.2.7|>=2.3,<2.3.1",
- "zendframework/zend-http": ">=2,<2.0.99|>=2.1,<2.1.99|>=2.3,<2.3.8|>=2.4,<2.4.1",
- "zendframework/zend-json": ">=2.1,<2.1.6|>=2.2,<2.2.6",
- "zendframework/zend-ldap": ">=2,<2.0.99|>=2.1,<2.1.99|>=2.2,<2.2.8|>=2.3,<2.3.3",
- "zendframework/zend-mail": ">=2,<2.4.11|>=2.5,<2.7.2",
- "zendframework/zend-navigation": ">=2,<2.2.7|>=2.3,<2.3.1",
- "zendframework/zend-session": ">=2,<2.0.99|>=2.1,<2.1.99|>=2.2,<2.2.9|>=2.3,<2.3.4",
- "zendframework/zend-validator": ">=2.3,<2.3.6",
- "zendframework/zend-view": ">=2,<2.2.7|>=2.3,<2.3.1",
- "zendframework/zend-xmlrpc": ">=2.1,<2.1.6|>=2.2,<2.2.6",
- "zendframework/zendframework": ">=2,<2.4.11|>=2.5,<2.5.1",
- "zendframework/zendframework1": "<1.12.20",
- "zendframework/zendopenid": ">=2,<2.0.2",
- "zendframework/zendxml": ">=1,<1.0.1",
- "zetacomponents/mail": "<1.8.2",
- "zf-commons/zfc-user": "<1.2.2",
- "zfcampus/zf-apigility-doctrine": ">=1,<1.0.3",
- "zfr/zfr-oauth2-server-module": "<0.1.2"
- },
- "type": "metapackage",
- "notification-url": "https://packagist.org/downloads/",
- "license": [
- "MIT"
- ],
- "authors": [
- {
- "name": "Marco Pivetta",
- "email": "ocramius@gmail.com",
- "role": "maintainer"
- }
- ],
- "description": "Prevents installation of composer packages with known security vulnerabilities: no API, simply require it",
- "time": "2017-12-24T19:52:27+00:00"
- },
- {
- "name": "squizlabs/php_codesniffer",
- "version": "2.9.1",
- "source": {
- "type": "git",
- "url": "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/squizlabs/PHP_CodeSniffer.git",
- "reference": "dcbed1074f8244661eecddfc2a675430d8d33f62"
- },
- "dist": {
- "type": "zip",
- "url": "https://api.github.com/repos/squizlabs/PHP_CodeSniffer/zipball/dcbed1074f8244661eecddfc2a675430d8d33f62",
- "reference": "dcbed1074f8244661eecddfc2a675430d8d33f62",
- "shasum": ""
- },
- "require": {
- "ext-simplexml": "*",
- "ext-tokenizer": "*",
- "ext-xmlwriter": "*",
- "php": ">=5.1.2"
- },
- "require-dev": {
- "phpunit/phpunit": "~4.0"
- },
- "bin": [
- "scripts/phpcs",
- "scripts/phpcbf"
- ],
- "type": "library",
- "extra": {
- "branch-alias": {
- "dev-master": "2.x-dev"
- }
- },
- "autoload": {
- "classmap": [
- "CodeSniffer.php",
- "CodeSniffer/CLI.php",
- "CodeSniffer/Exception.php",
- "CodeSniffer/File.php",
- "CodeSniffer/Fixer.php",
- "CodeSniffer/Report.php",
- "CodeSniffer/Reporting.php",
- "CodeSniffer/Sniff.php",
- "CodeSniffer/Tokens.php",
- "CodeSniffer/Reports/",
- "CodeSniffer/Tokenizers/",
- "CodeSniffer/DocGenerators/",
- "CodeSniffer/Standards/AbstractPatternSniff.php",
- "CodeSniffer/Standards/AbstractScopeSniff.php",
- "CodeSniffer/Standards/AbstractVariableSniff.php",
- "CodeSniffer/Standards/IncorrectPatternException.php",
- "CodeSniffer/Standards/Generic/Sniffs/",
- "CodeSniffer/Standards/MySource/Sniffs/",
- "CodeSniffer/Standards/PEAR/Sniffs/",
- "CodeSniffer/Standards/PSR1/Sniffs/",
- "CodeSniffer/Standards/PSR2/Sniffs/",
- "CodeSniffer/Standards/Squiz/Sniffs/",
- "CodeSniffer/Standards/Zend/Sniffs/"
- ]
- },
- "notification-url": "https://packagist.org/downloads/",
- "license": [
- "BSD-3-Clause"
- ],
- "authors": [
- {
- "name": "Greg Sherwood",
- "role": "lead"
- }
- ],
- "description": "PHP_CodeSniffer tokenizes PHP, JavaScript and CSS files and detects violations of a defined set of coding standards.",
- "homepage": "http://www.squizlabs.com/php-codesniffer",
- "keywords": [
- "phpcs",
- "standards"
- ],
- "time": "2017-05-22T02:43:20+00:00"
- },
- {
- "name": "wimg/php-compatibility",
- "version": "8.0.1",
- "source": {
- "type": "git",
- "url": "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/wimg/PHPCompatibility.git",
- "reference": "4c4385fb891dff0501009670f988d4fe36785249"
- },
- "dist": {
- "type": "zip",
- "url": "https://api.github.com/repos/wimg/PHPCompatibility/zipball/4c4385fb891dff0501009670f988d4fe36785249",
- "reference": "4c4385fb891dff0501009670f988d4fe36785249",
- "shasum": ""
- },
- "require": {
- "php": ">=5.3",
- "squizlabs/php_codesniffer": "^2.2 || ^3.0.2"
- },
- "conflict": {
- "squizlabs/php_codesniffer": "2.6.2"
- },
- "require-dev": {
- "phpunit/phpunit": "^4.0 || ^5.0 || ^6.0"
- },
- "suggest": {
- "dealerdirect/phpcodesniffer-composer-installer": "^0.4.1"
- },
- "type": "phpcodesniffer-standard",
- "autoload": {
- "psr-4": {
- "PHPCompatibility\\": "PHPCompatibility/"
- }
- },
- "notification-url": "https://packagist.org/downloads/",
- "license": [
- "LGPL-3.0"
- ],
- "authors": [
- {
- "name": "Wim Godden",
- "role": "lead"
- }
- ],
- "description": "A set of sniffs for PHP_CodeSniffer that checks for PHP version compatibility.",
- "homepage": "http://techblog.wimgodden.be/tag/codesniffer/",
- "keywords": [
- "compatibility",
- "phpcs",
- "standards"
- ],
- "time": "2017-08-07T19:39:05+00:00"
- },
- {
- "name": "wp-coding-standards/wpcs",
- "version": "0.13.1",
- "source": {
- "type": "git",
- "url": "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/WordPress-Coding-Standards/WordPress-Coding-Standards.git",
- "reference": "1f64b1a0b5b789822d0303436ee4e30e0135e4dc"
- },
- "dist": {
- "type": "zip",
- "url": "https://api.github.com/repos/WordPress-Coding-Standards/WordPress-Coding-Standards/zipball/1f64b1a0b5b789822d0303436ee4e30e0135e4dc",
- "reference": "1f64b1a0b5b789822d0303436ee4e30e0135e4dc",
- "shasum": ""
- },
- "require": {
- "php": ">=5.3",
- "squizlabs/php_codesniffer": "^2.9.0 || ^3.0.2"
- },
- "suggest": {
- "dealerdirect/phpcodesniffer-composer-installer": "^0.4.1"
- },
- "type": "phpcodesniffer-standard",
- "notification-url": "https://packagist.org/downloads/",
- "license": [
- "MIT"
- ],
- "authors": [
- {
- "name": "Contributors",
- "homepage": "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/WordPress-Coding-Standards/WordPress-Coding-Standards/graphs/contributors"
- }
- ],
- "description": "PHP_CodeSniffer rules (sniffs) to enforce WordPress coding conventions",
- "keywords": [
- "phpcs",
- "standards",
- "wordpress"
- ],
- "time": "2017-08-05T16:08:58+00:00"
- }
- ],
- "aliases": [],
- "minimum-stability": "dev",
- "stability-flags": {
- "roave/security-advisories": 20
- },
- "prefer-stable": true,
- "prefer-lowest": false,
- "platform": {
- "php": ">=5.3.29"
- },
- "platform-dev": [],
- "platform-overrides": {
- "php": "5.3.29"
- }
-}
diff --git a/features/aliases.feature b/features/aliases.feature
index 22569faeab..abd8942127 100644
--- a/features/aliases.feature
+++ b/features/aliases.feature
@@ -9,23 +9,22 @@ Feature: Create shortcuts to specific WordPress installs
path: foo
"""
- When I try `wp core is-installed`
+ When I mistakenly try `wp core is-installed`
Then STDERR should contain:
"""
Error: This does not seem to be a WordPress install.
"""
- And the return code should be 1
When I run `wp @foo core is-installed`
Then the return code should be 0
- When I run `cd bar; wp @foo core is-installed`
+ When I run `cd bar && wp @foo core is-installed`
Then the return code should be 0
Scenario: Error when invalid alias provided
Given an empty directory
- When I try `wp @test option get home`
+ When I mistakenly try `wp @test option get home`
Then STDERR should be:
"""
Error: Alias '@test' not found.
@@ -39,7 +38,7 @@ Feature: Create shortcuts to specific WordPress installs
path: foo
"""
- When I try `wp @test option get home`
+ When I mistakenly try `wp @test option get home`
Then STDERR should be:
"""
Error: Alias '@test' not found.
@@ -60,7 +59,7 @@ Feature: Create shortcuts to specific WordPress installs
http://example.com
"""
- When I try `wp @foo option get home --path=foo`
+ When I mistakenly try `wp @foo option get home --path=foo`
Then STDERR should contain:
"""
Parameter errors:
@@ -89,7 +88,7 @@ Feature: Create shortcuts to specific WordPress installs
1
"""
- When I try `wp @foo eval 'echo get_current_user_id();' --user=admin`
+ When I mistakenly try `wp @foo eval 'echo get_current_user_id();' --user=admin`
Then STDERR should contain:
"""
Parameter errors:
@@ -123,15 +122,12 @@ Feature: Create shortcuts to specific WordPress installs
path: foo
"""
- When I run `wp eval --skip-wordpress 'echo realpath( getenv( "RUN_DIR" ) );'`
- Then save STDOUT as {TEST_DIR}
-
When I run `wp cli alias`
Then STDOUT should be YAML containing:
"""
@all: Run command against every registered alias.
@foo:
- path: {TEST_DIR}/foo
+ path: {RUN_DIR}/foo
"""
When I run `wp cli aliases`
@@ -139,13 +135,13 @@ Feature: Create shortcuts to specific WordPress installs
"""
@all: Run command against every registered alias.
@foo:
- path: {TEST_DIR}/foo
+ path: {RUN_DIR}/foo
"""
When I run `wp cli alias --format=json`
Then STDOUT should be JSON containing:
"""
- {"@all":"Run command against every registered alias.","@foo":{"path":"{TEST_DIR}/foo"}}
+ {"@all":"Run command against every registered alias.","@foo":{"path":"{RUN_DIR}/foo"}}
"""
Scenario: Defining a project alias completely overrides a global alias
@@ -167,7 +163,7 @@ Feature: Create shortcuts to specific WordPress installs
@foo:
path: none-existent-install
"""
- When I try `WP_CLI_CONFIG_PATH=config.yml wp @foo option get home`
+ When I mistakenly try `WP_CLI_CONFIG_PATH=config.yml wp @foo option get home`
Then STDERR should contain:
"""
Error: This does not seem to be a WordPress install.
@@ -204,7 +200,7 @@ Feature: Create shortcuts to specific WordPress installs
http://google.com
"""
- When I try `wp @invalid option get home`
+ When I mistakenly try `wp @invalid option get home`
Then STDERR should be:
"""
Error: Group '@invalid' contains one or more invalid aliases: @baz
@@ -287,7 +283,7 @@ Feature: Create shortcuts to specific WordPress installs
Scenario: Error when '@all' is used without aliases defined
Given an empty directory
- When I try `wp @all option get home`
+ When I mistakenly try `wp @all option get home`
Then STDERR should be:
"""
Error: Cannot use '@all' when no aliases are registered.
@@ -317,7 +313,7 @@ Feature: Create shortcuts to specific WordPress installs
http://subsite.example.com
"""
- When I try `wp @subsite option get siteurl --url=subsite.example.com`
+ When I mistakenly try `wp @subsite option get siteurl --url=subsite.example.com`
Then STDERR should be:
"""
Error: Parameter errors:
@@ -338,7 +334,7 @@ Feature: Create shortcuts to specific WordPress installs
- @bar
"""
- When I try `wp core is-installed --allow-root --debug`
+ When I mistakenly try `wp core is-installed --allow-root --debug`
Then STDERR should contain:
"""
Error: This does not seem to be a WordPress install.
@@ -347,7 +343,6 @@ Feature: Create shortcuts to specific WordPress installs
"""
core is-installed --allow-root --debug
"""
- And the return code should be 1
When I try `wp @foo core is-installed --allow-root --debug`
Then the return code should be 0
@@ -356,7 +351,7 @@ Feature: Create shortcuts to specific WordPress installs
@foo core is-installed --allow-root --debug
"""
- When I try `cd bar; wp @bar core is-installed --allow-root --debug`
+ When I try `cd bar && wp @bar core is-installed --allow-root --debug`
Then the return code should be 0
And STDERR should contain:
"""
@@ -392,12 +387,11 @@ Feature: Create shortcuts to specific WordPress installs
- @bar
"""
- When I try `{INVOKE_WP_CLI_WITH_PHP_ARGS--ddisable_functions=} @foobar core is-installed`
+ When I mistakenly try `{INVOKE_WP_CLI_WITH_PHP_ARGS--ddisable_functions=} @foobar core is-installed`
Then STDERR should contain:
"""
Error: Cannot do 'group alias': The PHP functions `proc_open()` and/or `proc_close()` are disabled
"""
- And the return code should be 1
Examples:
| func |
diff --git a/features/bootstrap.feature b/features/bootstrap.feature
index 8869736a81..b21330243c 100644
--- a/features/bootstrap.feature
+++ b/features/bootstrap.feature
@@ -148,7 +148,7 @@ Feature: Bootstrap WP-CLI
Scenario: Override command bundled with freshly built PHAR
Given an empty directory
- And a new Phar with the same version
+ And a new Phar with the same version and cli build
And a cli-override-command/cli.php file:
"""
autoload->files as $file ) {
$contents .= ' - ' . dirname( dirname( dirname( __FILE__ ) ) ) . '/' . $file . PHP_EOL;
}
- @mkdir( sys_get_temp_dir() . '/wp-cli-package-test/' );
- $project_config = sys_get_temp_dir() . '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/wp-cli-package-test/config.yml';
+ @mkdir( Utils\get_temp_dir() . 'wp-cli-package-test/' );
+ $project_config = Utils\get_temp_dir() . 'wp-cli-package-test/config.yml';
file_put_contents( $project_config, $contents );
putenv( 'WP_CLI_CONFIG_PATH=' . $project_config );
}
}
// Inside WP-CLI
} else {
- require_once __DIR__ . '/../../php/utils.php';
- require_once __DIR__ . '/../../php/WP_CLI/Process.php';
- require_once __DIR__ . '/../../php/WP_CLI/ProcessRun.php';
+ require __DIR__ . '/../../php/utils.php';
+ require __DIR__ . '/../../php/WP_CLI/Process.php';
+ require __DIR__ . '/../../php/WP_CLI/ProcessRun.php';
if ( file_exists( __DIR__ . '/../../vendor/autoload.php' ) ) {
- require_once __DIR__ . '/../../vendor/autoload.php';
+ require __DIR__ . '/../../vendor/autoload.php';
} else if ( file_exists( __DIR__ . '/../../../../autoload.php' ) ) {
- require_once __DIR__ . '/../../../../autoload.php';
+ require __DIR__ . '/../../../../autoload.php';
}
}
@@ -81,6 +81,12 @@ class FeatureContext extends BehatContext implements ClosuredContextInterface {
'dbhost' => '127.0.0.1',
);
+ /**
+ * Variables for `do_mysqli()`.
+ */
+ private static $dbh = null; // Database handle.
+ private static $db_selected = false; // Whether database selected (opened).
+
/**
* Array of background process ids started by the current scenario. Used to terminate them at the end of the scenario.
*/
@@ -118,32 +124,16 @@ private static function get_process_env_variables() {
// Ensure we're using the expected `wp` binary
$bin_dir = getenv( 'WP_CLI_BIN_DIR' ) ?: realpath( __DIR__ . '/../../bin' );
$vendor_dir = realpath( __DIR__ . '/../../vendor/bin' );
- $path_separator = Utils\is_windows() ? ';' : ':';
$env = array(
- 'PATH' => $bin_dir . $path_separator . $vendor_dir . $path_separator . getenv( 'PATH' ),
+ 'PATH' => $bin_dir . PATH_SEPARATOR . $vendor_dir . PATH_SEPARATOR . getenv( 'PATH' ),
'BEHAT_RUN' => 1,
- 'HOME' => sys_get_temp_dir() . '/wp-cli-home',
+ 'HOME' => Utils\get_temp_dir() . 'wp-cli-home',
);
- if ( $config_path = getenv( 'WP_CLI_CONFIG_PATH' ) ) {
- $env['WP_CLI_CONFIG_PATH'] = $config_path;
- }
- if ( $term = getenv( 'TERM' ) ) {
- $env['TERM'] = $term;
- }
- if ( $php_args = getenv( 'WP_CLI_PHP_ARGS' ) ) {
- $env['WP_CLI_PHP_ARGS'] = $php_args;
- }
- if ( $php_used = getenv( 'WP_CLI_PHP_USED' ) ) {
- $env['WP_CLI_PHP_USED'] = $php_used;
- }
- if ( $php = getenv( 'WP_CLI_PHP' ) ) {
- $env['WP_CLI_PHP'] = $php;
- }
- if ( $travis_build_dir = getenv( 'TRAVIS_BUILD_DIR' ) ) {
- $env['TRAVIS_BUILD_DIR'] = $travis_build_dir;
- }
- if ( $github_token = getenv( 'GITHUB_TOKEN' ) ) {
- $env['GITHUB_TOKEN'] = $github_token;
+ $env_keys = array( 'GITHUB_TOKEN', 'SHELL', 'SYSTEMROOT', 'TERM', 'TMP', 'TRAVIS_BUILD_DIR', 'WP_CLI_CONFIG_PATH', 'WP_CLI_PHP', 'WP_CLI_PHP_ARGS', 'WP_CLI_PHP_USED' );
+ foreach ( $env_keys as $env_key ) {
+ if ( $env_val = getenv( $env_key ) ) {
+ $env[ $env_key ] = $env_val;
+ }
}
return $env;
}
@@ -154,7 +144,7 @@ private static function get_process_env_variables() {
*/
private static function cache_wp_files() {
$wp_version_suffix = ( $wp_version = getenv( 'WP_VERSION' ) ) ? "-$wp_version" : '';
- self::$cache_dir = sys_get_temp_dir() . '/wp-cli-test-core-download-cache' . $wp_version_suffix;
+ self::$cache_dir = Utils\get_temp_dir() . 'wp-cli-test-core-download-cache' . $wp_version_suffix;
if ( is_readable( self::$cache_dir . '/wp-config-sample.php' ) )
return;
@@ -186,7 +176,7 @@ public static function prepare( SuiteEvent $event ) {
// Remove install cache if any (not setting the static var).
$wp_version_suffix = ( $wp_version = getenv( 'WP_VERSION' ) ) ? "-$wp_version" : '';
- $install_cache_dir = sys_get_temp_dir() . '/wp-cli-test-core-install-cache' . $wp_version_suffix;
+ $install_cache_dir = Utils\get_temp_dir() . 'wp-cli-test-core-install-cache' . $wp_version_suffix;
if ( file_exists( $install_cache_dir ) ) {
self::remove_dir( $install_cache_dir );
}
@@ -201,8 +191,13 @@ public static function afterSuite( SuiteEvent $event ) {
self::$composer_local_repository = null;
}
- if ( self::$log_run_times ) {
- self::log_run_times_after_suite( $event );
+ if ( ! $event->isCompleted() ) {
+ // Then ctrl+C hit so cleanup any leftover scenario stuff.
+ self::afterScenario_cleanup( $event );
+ } else {
+ if ( self::$log_run_times ) {
+ self::log_run_times_after_suite( $event );
+ }
}
}
@@ -228,33 +223,45 @@ public function beforeScenario( $event ) {
*/
public function afterScenario( $event ) {
+ self::afterScenario_cleanup( $event, $this );
+
+ if ( self::$log_run_times ) {
+ self::log_run_times_after_scenario( $event );
+ }
+ }
+
+ /**
+ * Helper to cleanup after a scenario.
+ * If called from afterSuite() then suite was aborted and `$_this` won't be set.
+ */
+ private static function afterScenario_cleanup( $event, $_this = null ) {
+ if ( $_this ) {
+ // Remove any background processes first.
+ foreach ( $_this->running_procs as $proc ) {
+ $status = proc_get_status( $proc );
+ self::terminate_proc( $status['pid'] );
+ }
+ }
+
if ( self::$run_dir ) {
- // remove altered WP install, unless there's an error
- if ( $event->getResult() < 4 ) {
+ // Remove altered WP install unless suite did complete (`$_this` set) and there's an error.
+ if ( ! $_this || $event->getResult() < 4 ) {
self::remove_dir( self::$run_dir );
}
self::$run_dir = null;
}
- // Remove WP-CLI package directory if any. Set to `wp package path` by package-command and scaffold-package-command features, and by cli-info.feature.
- if ( isset( $this->variables['PACKAGE_PATH'] ) ) {
- self::remove_dir( $this->variables['PACKAGE_PATH'] );
- }
-
// Remove SUITE_CACHE_DIR if any.
if ( self::$suite_cache_dir ) {
self::remove_dir( self::$suite_cache_dir );
self::$suite_cache_dir = null;
}
- // Remove any background processes.
- foreach ( $this->running_procs as $proc ) {
- $status = proc_get_status( $proc );
- self::terminate_proc( $status['pid'] );
- }
-
- if ( self::$log_run_times ) {
- self::log_run_times_after_scenario( $event );
+ if ( $_this ) {
+ // Remove WP-CLI package directory if any. Set to `wp package path` by package-command and scaffold-package-command features, and by cli-info.feature.
+ if ( isset( $_this->variables['PACKAGE_PATH'] ) ) {
+ self::remove_dir( $_this->variables['PACKAGE_PATH'] );
+ }
}
}
@@ -280,7 +287,7 @@ private static function terminate_proc( $master_pid ) {
$errno = posix_get_last_error();
// Ignore "No such process" error as that's what we want.
if ( 3 /*ESRCH*/ !== $errno ) {
- throw new RuntimeException( posix_strerror( $errno ) );
+ throw new \RuntimeException( posix_strerror( $errno ) );
}
}
}
@@ -292,7 +299,7 @@ public static function create_cache_dir() {
if ( self::$suite_cache_dir ) {
self::remove_dir( self::$suite_cache_dir );
}
- self::$suite_cache_dir = sys_get_temp_dir() . '/' . uniqid( 'wp-cli-test-suite-cache-' . self::$temp_dir_infix . '-', TRUE );
+ self::$suite_cache_dir = Utils\get_temp_dir() . uniqid( 'wp-cli-test-suite-cache-' . self::$temp_dir_infix . '-', TRUE );
mkdir( self::$suite_cache_dir );
return self::$suite_cache_dir;
}
@@ -399,7 +406,7 @@ private function replace_wp_versions( $str ) {
$wp_versions = array();
$response = Requests::get( 'https://api.wordpress.org/core/version-check/1.7/', null, array( 'timeout' => 30 ) );
- if ( 200 === $response->status_code && ( $body = json_decode( $response->body ) ) && is_object( $body ) && isset( $body->offers ) && is_array( $body->offers ) ) {
+ if ( 200 === (int) $response->status_code && ( $body = json_decode( $response->body ) ) && is_object( $body ) && isset( $body->offers ) && is_array( $body->offers ) ) {
// Latest version alias.
$wp_versions["{WP_VERSION-latest}"] = count( $body->offers ) ? $body->offers[0]->version : '';
foreach ( $body->offers as $offer ) {
@@ -421,6 +428,37 @@ private function replace_wp_versions( $str ) {
return strtr( $str, $wp_versions );
}
+ /**
+ * Substitute "{INVOKE_WP_CLI_WITH_PHP_ARGS-args}" variables.
+ */
+ private function _replace_invoke_wp_cli_with_php_args( $str ) {
+ static $phar_path = null, $shell_path = null;
+
+ if ( null === $phar_path ) {
+ $phar_path = false;
+ if ( ( $bin_dir = getenv( 'WP_CLI_BIN_DIR' ) ) && file_exists( $bin_dir . '/wp' ) && is_executable( $bin_dir . '/wp' ) ) {
+ $phar_path = $bin_dir . '/wp';
+ } else {
+ $src_dir = dirname( dirname( __DIR__ ) );
+ $bin_path = $src_dir . '/bin/wp';
+ $vendor_bin_path = $src_dir . '/vendor/bin/wp';
+ if ( file_exists( $bin_path ) && is_executable( $bin_path ) ) {
+ $shell_path = $bin_path;
+ } elseif ( file_exists( $vendor_bin_path ) && is_executable( $vendor_bin_path ) ) {
+ $shell_path = $vendor_bin_path;
+ } else {
+ $shell_path = 'wp';
+ }
+ }
+ }
+
+ $str = preg_replace_callback( '/{INVOKE_WP_CLI_WITH_PHP_ARGS-([^}]*)}/', function ( $matches ) use ( $phar_path, $shell_path ) {
+ return $phar_path ? "php {$matches[1]} {$phar_path}" : ( 'WP_CLI_PHP_ARGS=' . escapeshellarg( $matches[1] ) . ' ' . $shell_path );
+ }, $str );
+
+ return $str;
+ }
+
/**
* Get the file and line number for the current behat event.
*/
@@ -443,12 +481,18 @@ private static function get_event_file( $event, &$line ) {
*/
public function create_run_dir() {
if ( !isset( $this->variables['RUN_DIR'] ) ) {
- self::$run_dir = $this->variables['RUN_DIR'] = sys_get_temp_dir() . '/' . uniqid( 'wp-cli-test-run-' . self::$temp_dir_infix . '-', TRUE );
+ self::$run_dir = $this->variables['RUN_DIR'] = Utils\get_temp_dir() . uniqid( 'wp-cli-test-run-' . self::$temp_dir_infix . '-', TRUE );
mkdir( $this->variables['RUN_DIR'] );
}
}
- public function build_phar( $version = 'same' ) {
+ /**
+ * Build a phar based on whatever's in the directory from which behat is run.
+ *
+ * @param string $version Version to set it to. (Note: has no correspondence with the actual version of the contained source.)
+ * @param string $build If set to "cli" will do a fast build without any bundled commands - "cli" command only. Defaults to '' (full build).
+ */
+ public function build_phar( $version = 'same', $build = '' ) {
$this->variables['PHAR_PATH'] = $this->variables['RUN_DIR'] . '/' . uniqid( "wp-cli-build-", TRUE ) . '.phar';
// Test running against a package installed as a WP-CLI dependency
@@ -464,13 +508,17 @@ public function build_phar( $version = 'same' ) {
}
$this->proc( Utils\esc_cmd(
- 'php -dphar.readonly=0 %1$s %2$s --version=%3$s && chmod +x %2$s',
+ 'php -dphar.readonly=0 %1$s %2$s --version=%3$s --quiet --build=%4$s',
$make_phar_path,
$this->variables['PHAR_PATH'],
- $version
+ $version,
+ $build
) )->run_check();
}
+ /**
+ * Download a released phar from github.com. Note: not currently used in any test.
+ */
public function download_phar( $version = 'same' ) {
if ( 'same' === $version ) {
$version = WP_CLI_VERSION;
@@ -496,7 +544,7 @@ public function download_phar( $version = 'same' ) {
* CACHE_DIR is a cache for downloaded test data such as images. Lives until manually deleted.
*/
private function set_cache_dir() {
- $path = sys_get_temp_dir() . '/wp-cli-test-cache';
+ $path = Utils\get_temp_dir() . 'wp-cli-test-cache';
if ( ! file_exists( $path ) ) {
mkdir( $path );
}
@@ -522,20 +570,30 @@ private static function run_sql( $sql_cmd, $assoc_args = array(), $add_database
$start_time = microtime( true );
Utils\run_mysql_command( $sql_cmd, array_merge( $assoc_args, $default_assoc_args ) );
if ( self::$log_run_times ) {
- self::log_proc_method_run_time( 'run_sql ' . $sql_cmd, $start_time );
+ self::log_proc_method_run_time( $sql_cmd . ' ' . Utils\assoc_args_to_str( $assoc_args ), $start_time );
}
}
+ /**
+ * Create the `$db_settings['dbname']` test database. Called on a "Given a database" step and on the various "Given a WP install..." steps.
+ */
public function create_db() {
$dbname = self::$db_settings['dbname'];
- self::run_sql( 'mysql --no-defaults', array( 'execute' => "CREATE DATABASE IF NOT EXISTS $dbname" ) );
+ self::do_mysqli( "CREATE DATABASE IF NOT EXISTS `$dbname` CHARSET 'UTF8'" );
}
+ /**
+ * Drop the `$db_settings['dbname']` test database. Done at the beginning of every scenario.
+ */
public function drop_db() {
$dbname = self::$db_settings['dbname'];
- self::run_sql( 'mysql --no-defaults', array( 'execute' => "DROP DATABASE IF EXISTS $dbname" ) );
+ self::do_mysqli( "DROP DATABASE IF EXISTS `$dbname`" );
+ self::$db_selected = false;
}
+ /**
+ * Run a process from the RUN_DIR directory (or a sub-directory of it if given `$path`).
+ */
public function proc( $command, $assoc_args = array(), $path = '' ) {
if ( !empty( $assoc_args ) )
$command .= Utils\assoc_args_to_str( $assoc_args );
@@ -572,7 +630,7 @@ public function background_proc( $cmd ) {
if ( !$status['running'] ) {
$stderr = is_resource( $pipes[2] ) ? ( ': ' . stream_get_contents( $pipes[2] ) ) : '';
- throw new RuntimeException( sprintf( "Failed to start background process '%s'%s.", $cmd, $stderr ) );
+ throw new \RuntimeException( sprintf( "Failed to start background process '%s'%s.", $cmd, $stderr ) );
} else {
$this->running_procs[] = $proc;
}
@@ -602,16 +660,20 @@ public function add_line_to_wp_config( &$wp_config_code, $line ) {
$wp_config_code = str_replace( $token, "$line\n\n$token", $wp_config_code );
}
+ /**
+ * "Downloads" wp in the sense that it copies the version downloaded and cached by `cache_wp_files()` from CACHE_DIR to RUN_DIR (or a sub-directory of it if given `$subdir`).
+ */
public function download_wp( $subdir = '' ) {
- $dest_dir = $this->variables['RUN_DIR'] . "/$subdir";
+ $dest_dir = $this->variables['RUN_DIR'];
if ( $subdir ) {
- mkdir( $dest_dir );
+ $dest_dir = $this->variables['RUN_DIR'] . "/$subdir";
+ mkdir( $dest_dir, 0777, true /*recursive*/ );
}
self::copy_dir( self::$cache_dir, $dest_dir );
- // disable emailing
+ // Disable emailing - otherwise will get "sh: 1: -t: not found" error message on Travis (as PHP ini `sendmail_from` not set by default).
mkdir( $dest_dir . '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/wp-content/mu-plugins' );
copy( __DIR__ . '/../extra/no-mail.php', $dest_dir . '/wp-content/mu-plugins/no-mail.php' );
}
@@ -623,6 +685,7 @@ public function create_config( $subdir = '', $extra_php = false ) {
$params['dbprefix'] = $subdir ? preg_replace( '#[^a-zA-Z\_0-9]#', '_', $subdir ) : 'wp_';
$params['skip-salts'] = true;
+ $params['skip-check'] = true;
if( false !== $extra_php ) {
$params['extra-php'] = $extra_php;
@@ -646,12 +709,14 @@ public function create_config( $subdir = '', $extra_php = false ) {
public function install_wp( $subdir = '' ) {
$wp_version_suffix = ( $wp_version = getenv( 'WP_VERSION' ) ) ? "-$wp_version" : '';
- self::$install_cache_dir = sys_get_temp_dir() . '/wp-cli-test-core-install-cache' . $wp_version_suffix;
+ self::$install_cache_dir = Utils\get_temp_dir() . 'wp-cli-test-core-install-cache' . $wp_version_suffix;
if ( ! file_exists( self::$install_cache_dir ) ) {
mkdir( self::$install_cache_dir );
}
- $subdir = $this->replace_variables( $subdir );
+ if ( $subdir ) {
+ $subdir = $this->replace_variables( $subdir );
+ }
$this->create_db();
$this->create_run_dir();
@@ -675,13 +740,16 @@ public function install_wp( $subdir = '' ) {
if ( $install_cache_path && file_exists( $install_cache_path ) ) {
self::copy_dir( $install_cache_path, $run_dir );
- self::run_sql( 'mysql --no-defaults', array( 'execute' => "source {$install_cache_path}.sql" ), true /*add_database*/ );
+ self::do_mysqli_source( $install_cache_path . '.sql' );
} else {
$this->proc( 'wp core install', $install_args, $subdir )->run_check();
if ( $install_cache_path ) {
mkdir( $install_cache_path );
self::dir_diff_copy( $run_dir, self::$cache_dir, $install_cache_path );
- self::run_sql( 'mysqldump --no-defaults', array( 'result-file' => "{$install_cache_path}.sql" ), true /*add_database*/ );
+ $install_cache_sql = $install_cache_path . '.sql';
+ self::run_sql( 'mysqldump --no-defaults --skip-comments', array( 'result-file' => $install_cache_sql ), true /*add_database*/ );
+ // Remove conditional and lock tables statements.
+ file_put_contents( $install_cache_sql, preg_replace( array( '/^\/\*[^*]+\*\/;\n/m', '/^(?:UN)?LOCK TABLES[^;]*;\n/m' ), '', file_get_contents( $install_cache_sql ) ) );
}
}
}
@@ -714,11 +782,10 @@ public function install_wp_with_composer( $vendor_directory = 'vendor' ) {
public function composer_add_wp_cli_local_repository() {
if ( ! self::$composer_local_repository ) {
- self::$composer_local_repository = sys_get_temp_dir() . '/' . uniqid( "wp-cli-composer-local-", TRUE );
+ self::$composer_local_repository = Utils\get_temp_dir() . uniqid( "wp-cli-composer-local-", TRUE );
mkdir( self::$composer_local_repository );
- $env = self::get_process_env_variables();
- $src = isset( $env['TRAVIS_BUILD_DIR'] ) ? $env['TRAVIS_BUILD_DIR'] : realpath( __DIR__ . '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/../../' );
+ $src = getenv( 'TRAVIS_BUILD_DIR' ) ?: realpath( __DIR__ . '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/../../' );
self::copy_dir( $src, self::$composer_local_repository . '/' );
self::remove_dir( self::$composer_local_repository . '/.git' );
@@ -756,6 +823,69 @@ private function composer_command($cmd) {
$this->proc( $this->variables['COMPOSER_PATH'] . ' ' . $cmd )->run_check();
}
+ /**
+ * Do a MySQL query with `$db_settings`, using the PHP mysqli extension. Slightly faster than `run_sql()`.
+ *
+ * @param string $sql_cmd MySQL query.
+ * @param bool $open_database Whether to open (select) the database or not.
+ * @param bool $multi_query Whether the query contains multiple statements or not.
+ * @param bool $no_log If set won't log timing if using log run times.
+ */
+ private static function do_mysqli( $sql_cmd, $open_database = false, $multi_query = false, $no_log = false ) {
+ $start_time = microtime( true );
+
+ if ( null === self::$dbh ) {
+ if ( ! ( self::$dbh = mysqli_connect( self::$db_settings['dbhost'], self::$db_settings['dbuser'], self::$db_settings['dbpass'] ) ) ) {
+ throw new \RuntimeException(
+ sprintf( "Failed to connect to MySQL database host '%s', user '%s', pass '%s'.", self::$db_settings['dbhost'], self::$db_settings['dbuser'], self::$db_settings['dbpass'] )
+ );
+ }
+ }
+ if ( $open_database && ! self::$db_selected ) {
+ if ( ! mysqli_select_db( self::$dbh, self::$db_settings['dbname'] ) ) {
+ throw new \RuntimeException( sprintf( "Failed to open MySQL database name '%s'.", self::$db_settings['dbname'] ) );
+ }
+ self::$db_selected = true;
+ }
+ if ( $multi_query ) {
+ if ( ! mysqli_multi_query( self::$dbh, $sql_cmd ) ) {
+ throw new \RuntimeException( sprintf( "Failed to execute MySQL query '%s': %d: %s", $sql_cmd, mysqli_errno( self::$dbh ), mysqli_error( self::$dbh ) ) );
+ }
+ // Throw away the stored results (otherwise will get "out of sync" errors).
+ while ( mysqli_more_results( self::$dbh ) ) {
+ mysqli_next_result( self::$dbh );
+ }
+ } else {
+ if ( ! mysqli_query( self::$dbh, $sql_cmd ) ) {
+ throw new \RuntimeException( sprintf( "Failed to execute MySQL query '%s': %d: %s", $sql_cmd, mysqli_errno( self::$dbh ), mysqli_error( self::$dbh ) ) );
+ }
+ }
+ if ( self::$log_run_times && ! $no_log ) {
+ self::log_proc_method_run_time( 'do_mysqli ' . $sql_cmd, $start_time );
+ }
+ }
+
+ /**
+ * Do a MySQL SOURCE command using the PHP mysqli extension. Slightly faster than doing a mysql SOURCE command using `run_sql()`.
+ *
+ * @param string $source_file Name of MySQL source ".sql" file.
+ */
+ private static function do_mysqli_source( $source_file ) {
+ $start_time = microtime( true );
+
+ static $files = array();
+
+ if ( ! isset( $files[ $source_file ] ) ) {
+ $files[ $source_file ] = file_get_contents( $source_file );
+ }
+
+ self::do_mysqli( $files[ $source_file ], true /*open_database*/, true /*multi_query*/, true /*no_log*/ );
+
+ if ( self::$log_run_times ) {
+ self::log_proc_method_run_time( 'do_mysqli_source ' . $source_file, $start_time );
+ }
+ }
+
/**
* Initialize run time logging.
*/
diff --git a/features/bootstrap/support.php b/features/bootstrap/support.php
index 6aa17c6c39..6ad8fff47e 100644
--- a/features/bootstrap/support.php
+++ b/features/bootstrap/support.php
@@ -36,7 +36,7 @@ function checkString( $output, $expected, $action, $message = false ) {
switch ( $action ) {
case 'be':
- $r = $expected === rtrim( $output, "\n" );
+ $r = $expected === rtrim( _wp_cli_nocr( $output ), "\n" );
break;
case 'contain':
@@ -198,3 +198,27 @@ function checkThatYamlStringContainsYamlString( $actualYaml, $expectedYaml ) {
return compareContents( $expectedValue, $actualValue );
}
+/**
+ * Helper to strip carriage returns from input for Windows compat.
+ *
+ * @param string|array String or array of strings to strip.
+ * @return string|array String or array stripped of carriage returns.
+ */
+function _wp_cli_nocr( $str_or_arr ) {
+ if ( is_string( $str_or_arr ) ) {
+ return str_replace( "\r", '', $str_or_arr );
+ }
+ return array_map( function ( $str ) {
+ return str_replace( "\r", '', $str );
+ }, $str_or_arr );
+}
+
+/**
+ * Helper to convert *nix shell escaped command to Windows. Primitive.
+ *
+ * @param string $cmd Command to convert.
+ * @return string Command escaped for Windows - ie. single quotes converted to double quotes and vice versa.
+ */
+function _wp_cli_esc_cmd_win( $cmd ) {
+ return str_replace( array( "'", '"', '' ), array( '', "'", '"' ), $cmd );
+}
diff --git a/features/class-wp-cli.feature b/features/class-wp-cli.feature
new file mode 100644
index 0000000000..190d65ab7d
--- /dev/null
+++ b/features/class-wp-cli.feature
@@ -0,0 +1,17 @@
+Feature: Various utilities for WP-CLI commands
+
+ Scenario Outline: Check that `proc_open()` and `proc_close()` aren't disabled for `WP_CLI::launch()`
+ When I try `{INVOKE_WP_CLI_WITH_PHP_ARGS--ddisable_functions=} --skip-wordpress eval 'WP_CLI::launch( null );'`
+ Then STDERR should contain:
+ """
+ Error: Cannot do 'launch': The PHP functions `proc_open()` and/or `proc_close()` are disabled
+ """
+ And STDOUT should be empty
+ And the return code should be 1
+
+ Examples:
+ | func |
+ | proc_open |
+ | proc_close |
+
+
diff --git a/features/cli-bash-completion.feature b/features/cli-bash-completion.feature
index f442d4c92e..85108fd339 100644
--- a/features/cli-bash-completion.feature
+++ b/features/cli-bash-completion.feature
@@ -12,8 +12,6 @@ Feature: `wp cli completions` tasks
"""
server
"""
- And STDERR should be empty
- And the return code should be 0
When I run `wp cli completions --line="wp co" --point=100`
Then STDOUT should contain:
@@ -24,8 +22,6 @@ Feature: `wp cli completions` tasks
"""
core
"""
- And STDERR should be empty
- And the return code should be 0
When I run `wp cli completions --line="wp core " --point=100`
Then STDOUT should contain:
@@ -36,8 +32,6 @@ Feature: `wp cli completions` tasks
"""
update
"""
- And STDERR should be empty
- And the return code should be 0
When I run `wp cli completions --line="wp help " --point=100`
Then STDOUT should contain:
@@ -48,8 +42,6 @@ Feature: `wp cli completions` tasks
"""
media
"""
- And STDERR should be empty
- And the return code should be 0
When I run `wp cli completions --line="wp help language core " --point=100`
Then STDOUT should contain:
@@ -60,24 +52,18 @@ Feature: `wp cli completions` tasks
"""
update
"""
- And STDERR should be empty
- And the return code should be 0
When I run `wp cli completions --line="wp core" --point=100`
Then STDOUT should contain:
"""
core
"""
- And STDERR should be empty
- And the return code should be 0
When I run `wp cli completions --line="wp core " --point=100`
Then STDOUT should contain:
"""
download
"""
- And STDERR should be empty
- And the return code should be 0
When I run `wp cli completions --line='wp bogus-comand ' --point=100`
Then STDOUT should be empty
@@ -132,16 +118,12 @@ Feature: `wp cli completions` tasks
"""
server
"""
- And STDERR should be empty
- And the return code should be 0
When I run `wp cli completions --line="wp @e" --point=100`
Then STDOUT should contain:
"""
@example
"""
- And STDERR should be empty
- And the return code should be 0
When I run `wp cli completions --line="wp @example " --point=100`
Then STDOUT should not contain:
@@ -156,16 +138,12 @@ Feature: `wp cli completions` tasks
"""
eval
"""
- And STDERR should be empty
- And the return code should be 0
When I run `wp cli completions --line="wp @example plugin " --point=100`
Then STDOUT should contain:
"""
list
"""
- And STDERR should be empty
- And the return code should be 0
When I run `wp cli completions --line="wp help language core " --point=100`
Then STDOUT should contain:
@@ -176,8 +154,6 @@ Feature: `wp cli completions` tasks
"""
update
"""
- And STDERR should be empty
- And the return code should be 0
When I run `wp cli completions --line="wp help " --point=100`
Then STDOUT should not contain:
@@ -188,24 +164,18 @@ Feature: `wp cli completions` tasks
"""
post-type
"""
- And STDERR should be empty
- And the return code should be 0
When I run `wp cli completions --line="wp help core" --point=100`
Then STDOUT should contain:
"""
core
"""
- And STDERR should be empty
- And the return code should be 0
When I run `wp cli completions --line="wp help core " --point=100`
Then STDOUT should contain:
"""
download
"""
- And STDERR should be empty
- And the return code should be 0
Scenario: Bash Completion for global parameters
Given an empty directory
@@ -279,8 +249,6 @@ Feature: `wp cli completions` tasks
"""
--quiet=
"""
- And STDERR should be empty
- And the return code should be 0
When I run `wp cli completions --line="wp plugin list --path --p" --point=100`
Then STDOUT should contain:
diff --git a/features/cli-info.feature b/features/cli-info.feature
index 09918b2df4..7b24530af8 100644
--- a/features/cli-info.feature
+++ b/features/cli-info.feature
@@ -26,7 +26,7 @@ Feature: Review CLI information
When I run `wp cli info`
Then STDOUT should contain:
"""
- WP-CLI packages dir:
+ WP-CLI packages dir
"""
Scenario: Packages directory path should be slashed correctly
diff --git a/features/cli.feature b/features/cli.feature
index 0d7d38e939..f2b0a89a72 100644
--- a/features/cli.feature
+++ b/features/cli.feature
@@ -30,7 +30,7 @@ Feature: `wp cli` tasks
Scenario: Ability to set a custom version when building
Given an empty directory
And save the {SRC_DIR}/VERSION file as {TRUE_VERSION}
- And a new Phar with version "1.2.3"
+ And a new Phar with version "1.2.3" and cli build
When I run `{PHAR_PATH} cli version`
Then STDOUT should be:
@@ -45,19 +45,18 @@ Feature: `wp cli` tasks
@github-api
Scenario: Check for updates
Given an empty directory
- And a new Phar with version "0.0.0"
+ And a new Phar with version "0.0.0" and cli build
When I run `{PHAR_PATH} cli check-update`
Then STDOUT should contain:
"""
package_url
"""
- And STDERR should be empty
@github-api
Scenario: Do WP-CLI Update
Given an empty directory
- And a new Phar with version "0.0.0"
+ And a new Phar with version "0.0.0" and cli build
When I run `{PHAR_PATH} --info`
Then STDOUT should contain:
@@ -78,8 +77,6 @@ Feature: `wp cli` tasks
"""
Success:
"""
- And STDERR should be empty
- And the return code should be 0
When I run `{PHAR_PATH} --info`
Then STDOUT should contain:
@@ -100,7 +97,7 @@ Feature: `wp cli` tasks
@github-api
Scenario: Patch update from 0.14.0 to 0.14.1
Given an empty directory
- And a new Phar with version "0.14.0"
+ And a new Phar with version "0.14.0" and cli build
When I run `{PHAR_PATH} --version`
Then STDOUT should be:
@@ -117,8 +114,6 @@ Feature: `wp cli` tasks
"""
Success: Updated WP-CLI to 0.14.1
"""
- And STDERR should be empty
- And the return code should be 0
When I run `{PHAR_PATH} --version`
Then STDOUT should be:
@@ -129,7 +124,7 @@ Feature: `wp cli` tasks
@github-api
Scenario: Not a patch update from 0.14.0
Given an empty directory
- And a new Phar with version "0.14.0"
+ And a new Phar with version "0.14.0" and cli build
When I run `{PHAR_PATH} cli update --no-patch --yes`
Then STDOUT should contain:
@@ -140,13 +135,11 @@ Feature: `wp cli` tasks
"""
0.14.1
"""
- And STDERR should be empty
- And the return code should be 0
- @require-php-5.6
+ @github-api
Scenario: Install WP-CLI nightly
Given an empty directory
- And a new Phar with version "0.14.0"
+ And a new Phar with version "0.14.0" and cli build
When I run `{PHAR_PATH} cli update --nightly --yes`
Then STDOUT should contain:
@@ -158,13 +151,10 @@ Feature: `wp cli` tasks
Success: Updated WP-CLI to the latest nightly release.
"""
- And STDERR should be empty
- And the return code should be 0
-
@github-api
Scenario: Install WP-CLI stable
Given an empty directory
- And a new Phar with version "0.14.0"
+ And a new Phar with version "0.14.0" and cli build
And a session file:
"""
y
@@ -187,8 +177,6 @@ Feature: `wp cli` tasks
"""
Success: Updated WP-CLI to the latest stable release.
"""
- And STDERR should be empty
- And the return code should be 0
When I run `{PHAR_PATH} cli check-update`
Then STDOUT should be:
@@ -202,6 +190,125 @@ Feature: `wp cli` tasks
WP-CLI {UPDATE_VERSION}
"""
+ @github-api
+ Scenario: Install WP-CLI via auto-update
+ Given an empty directory
+ And an empty cache
+ And a new Phar with version "0.14.0" and cli build
+ And a session_no file:
+ """
+ n
+ """
+ And a session_yes_no file:
+ """
+ y
+ n
+ """
+ And a session_yes_yes file:
+ """
+ y
+ y
+ """
+
+ When I run `{PHAR_PATH} cli check-update --field=version | head -1`
+ Then STDOUT should not be empty
+ And save STDOUT as {UPDATE_VERSION}
+
+ Given a {SUITE_CACHE_DIR}/wp-cli-update-check file:
+ """
+ 1
+ """
+ When I run `SHELL_PIPE=0 {PHAR_PATH} help < session_no`
+ Then STDOUT should contain:
+ """
+ You have version 0.14.0. Would you like to check if an update of WP-CLI is available? [y/n]
+ """
+ And STDOUT should contain:
+ """
+ Continuing with your current command 'help'...
+ """
+ And STDOUT should contain:
+ """
+ wp
+ """
+ And STDOUT should not contain:
+ """
+ Checking for an update
+ """
+
+ Given a {SUITE_CACHE_DIR}/wp-cli-update-check file:
+ """
+ 1
+ """
+ When I run `SHELL_PIPE=0 {PHAR_PATH} help < session_yes_no`
+ Then STDOUT should contain:
+ """
+ You have version 0.14.0. Would you like to check if an update of WP-CLI is available? [y/n]
+ """
+ And STDOUT should contain:
+ """
+ Checking for an update of WP-CLI...
+ Update found - invoking 'cli update' (please note that if you decide to update, your current command 'help' will not complete)...
+ """
+ And STDOUT should contain:
+ """
+ You have version 0.14.0. Would you like to update to {UPDATE_VERSION}? [y/n]
+ """
+ And STDOUT should contain:
+ """
+ Continuing with your current command 'help'...
+ """
+ And STDOUT should contain:
+ """
+ wp
+ """
+ And STDOUT should not contain:
+ """
+ Downloading
+ """
+
+ Given a {SUITE_CACHE_DIR}/wp-cli-update-check file:
+ """
+ 1
+ """
+ When I run `SHELL_PIPE=0 {PHAR_PATH} help < session_yes_yes`
+ Then STDOUT should contain:
+ """
+ You have version 0.14.0. Would you like to check if an update of WP-CLI is available? [y/n]
+ """
+ And STDOUT should contain:
+ """
+ Checking for an update of WP-CLI...
+ Update found - invoking 'cli update' (please note that if you decide to update, your current command 'help' will not complete)...
+ You have version 0.14.0. Would you like to update to {UPDATE_VERSION}? [y/n]
+ """
+ And STDOUT should contain:
+ """
+ Downloading from https://github.com/wp-cli/wp-cli/releases/download/v{UPDATE_VERSION}/wp-cli-{UPDATE_VERSION}.phar...
+ """
+ And STDOUT should contain:
+ """
+ New version works. Proceeding to replace.
+ """
+ And STDOUT should contain:
+ """
+ Success:
+ """
+ And STDOUT should not contain:
+ """
+ Continuing
+ """
+ And STDOUT should not contain:
+ """
+ wp
+ """
+
+ When I run `{PHAR_PATH} cli check-update`
+ Then STDOUT should be:
+ """
+ Success: WP-CLI is at the latest version.
+ """
+
Scenario: Dump the list of global parameters with values
Given a WP installation
@@ -210,5 +317,3 @@ Feature: `wp cli` tasks
"""
17"current":
"""
- And STDERR should be empty
- And the return code should be 0
diff --git a/features/command.feature b/features/command.feature
index 6c287c777c..6cf3313782 100644
--- a/features/command.feature
+++ b/features/command.feature
@@ -15,12 +15,6 @@ Feature: WP-CLI Commands
wp cap
"""
- When I run `wp checksum --help`
- Then STDOUT should contain:
- """
- wp checksum
- """
-
When I run `wp comment --help`
Then STDOUT should contain:
"""
@@ -260,9 +254,8 @@ Feature: WP-CLI Commands
WP_CLI::add_command( 'command example', 'Non_Existent_Class' );
"""
- When I try `wp --require=custom-cmd.php help`
- Then the return code should be 1
- And STDERR should contain:
+ When I mistakenly try `wp --require=custom-cmd.php help`
+ Then STDERR should contain:
"""
Callable "Non_Existent_Class" does not exist, and cannot be registered as `wp command example`.
"""
@@ -285,7 +278,7 @@ Feature: WP-CLI Commands
WP_CLI::add_command( 'command', 'Custom_Command_Class' );
"""
- When I try `wp --require=custom-cmd.php command invalid`
+ When I mistakenly try `wp --require=custom-cmd.php command invalid`
Then STDERR should contain:
"""
Error: 'invalid' is not a registered subcommand of 'command'. See 'wp help command' for available subcommands.
@@ -322,7 +315,7 @@ Feature: WP-CLI Commands
My awesome closure command
"""
- When I try `wp --require=custom-cmd.php foo bar --burrito`
+ When I mistakenly try `wp --require=custom-cmd.php foo bar --burrito`
Then STDERR should contain:
"""
unknown --burrito parameter
@@ -365,7 +358,7 @@ Feature: WP-CLI Commands
My awesome function command
"""
- When I try `wp --require=custom-cmd.php foo bar --burrito`
+ When I mistakenly try `wp --require=custom-cmd.php foo bar --burrito`
Then STDERR should contain:
"""
unknown --burrito parameter
@@ -415,7 +408,7 @@ Feature: WP-CLI Commands
My awesome class method command
"""
- When I try `wp --require=custom-cmd.php foo bar --burrito`
+ When I mistakenly try `wp --require=custom-cmd.php foo bar --burrito`
Then STDERR should contain:
"""
unknown --burrito parameter
@@ -460,7 +453,7 @@ Feature: WP-CLI Commands
My awesome class method command
"""
- When I try `wp --require=custom-cmd.php foo bar --burrito`
+ When I mistakenly try `wp --require=custom-cmd.php foo bar --burrito`
Then STDERR should contain:
"""
unknown --burrito parameter
@@ -501,7 +494,6 @@ Feature: WP-CLI Commands
"""
bar
"""
- And STDERR should be empty
Scenario: Use an invalid class method as a command
Given an empty directory
@@ -525,7 +517,7 @@ Feature: WP-CLI Commands
WP_CLI::add_command( 'bar', array( $foo, 'bar' ) );
"""
- When I try `wp --require=custom-cmd.php bar`
+ When I mistakenly try `wp --require=custom-cmd.php bar`
Then STDERR should contain:
"""
Error: Callable ["Foo_Class","bar"] does not exist, and cannot be registered as `wp bar`.
@@ -623,13 +615,13 @@ Feature: WP-CLI Commands
---
"""
- When I try `wp foo nana --apple=fuji`
+ When I mistakenly try `wp foo nana --apple=fuji`
Then STDERR should contain:
"""
Error: Invalid value specified for positional arg.
"""
- When I try `wp foo hello --apple=fuji --meal=snack`
+ When I mistakenly try `wp foo hello --apple=fuji --meal=snack`
Then STDERR should contain:
"""
Invalid value specified for 'meal' (A type of meal.)
@@ -769,11 +761,104 @@ Feature: WP-CLI Commands
When I run `wp help foo`
Then STDOUT should contain:
"""
- EXAMPLES
+ NAME
+
+ wp foo
+
+ DESCRIPTION
+
+ My awesome function command
+
+ SYNOPSIS
+
+ wp foo
+
+ EXAMPLES
+
+ # Run the custom foo command
+
+ GLOBAL PARAMETERS
+
"""
- And STDOUT should contain:
+
+ # With synopsis, appended.
+ Given a hello-command.php file:
"""
- # Run the custom foo command
+ 'Prints a greeting.',
+ 'synopsis' => array(
+ array(
+ 'type' => 'positional',
+ 'name' => 'name',
+ 'description' => 'Name of person to greet.',
+ 'optional' => false,
+ 'repeating' => false,
+ ),
+ array(
+ 'type' => 'assoc',
+ 'name' => 'type',
+ 'optional' => true,
+ 'default' => 'success',
+ 'options' => array( 'success', 'error' ),
+ ),
+ array(
+ 'type' => 'flag',
+ 'name' => 'honk',
+ 'optional' => true,
+ ),
+ ),
+ 'when' => 'after_wp_load',
+ 'longdesc' => "\r\n## EXAMPLES\n\n# Say hello to Newman\nwp example hello Newman\nSuccess: Hello, Newman!",
+ ) );
+ """
+
+ When I run `wp --require=hello-command.php help example hello`
+ Then STDOUT should contain:
+ """
+ NAME
+
+ wp example hello
+
+ DESCRIPTION
+
+ Prints a greeting.
+
+ SYNOPSIS
+
+ wp example hello [--type=] [--honk]
+
+ OPTIONS
+
+
+ Name of person to greet.
+
+ [--type=]
+ ---
+ default: success
+ options:
+ - success
+ - error
+ ---
+
+ [--honk]
+
+ EXAMPLES
+
+ # Say hello to Newman
+ wp example hello Newman
+ Success: Hello, Newman!
+
+ GLOBAL PARAMETERS
+
"""
Scenario: Register a command with default and accepted arguments.
@@ -846,7 +931,6 @@ Feature: WP-CLI Commands
shop:
burrito:
"""
- And STDERR should be empty
When I run `wp --require=test-cmd.php foo ''`
Then STDOUT should be YAML containing:
@@ -855,7 +939,6 @@ Feature: WP-CLI Commands
shop:
burrito:
"""
- And STDERR should be empty
When I run `wp --require=test-cmd.php foo apple --burrito=veggies`
Then STDOUT should be YAML containing:
@@ -864,29 +947,28 @@ Feature: WP-CLI Commands
shop:
burrito: veggies
"""
- And STDERR should be empty
- When I try `wp --require=test-cmd.php foo apple --burrito=meat`
+ When I mistakenly try `wp --require=test-cmd.php foo apple --burrito=meat`
Then STDERR should contain:
"""
Error: Parameter errors:
Invalid value specified for 'burrito' (This is the burrito argument.)
"""
- When I try `wp --require=test-cmd.php foo apple --burrito=''`
+ When I mistakenly try `wp --require=test-cmd.php foo apple --burrito=''`
Then STDERR should contain:
"""
Error: Parameter errors:
Invalid value specified for 'burrito' (This is the burrito argument.)
"""
- When I try `wp --require=test-cmd.php foo apple taco_del_mar`
+ When I mistakenly try `wp --require=test-cmd.php foo apple taco_del_mar`
Then STDERR should contain:
"""
Error: Invalid value specified for positional arg.
"""
- When I try `wp --require=test-cmd.php foo apple 'cha cha cha' taco_del_mar`
+ When I mistakenly try `wp --require=test-cmd.php foo apple 'cha cha cha' taco_del_mar`
Then STDERR should contain:
"""
Error: Invalid value specified for positional arg.
@@ -899,7 +981,6 @@ Feature: WP-CLI Commands
shop: cha cha cha
burrito:
"""
- And STDERR should be empty
Scenario: Register a command with default and accepted arguments, part two
Given an empty directory
@@ -933,16 +1014,14 @@ Feature: WP-CLI Commands
"""
burrito:
"""
- And STDERR should be empty
When I run `wp --require=test-cmd.php foo beans`
Then STDOUT should be YAML containing:
"""
burrito: beans
"""
- And STDERR should be empty
- When I try `wp --require=test-cmd.php foo apple`
+ When I mistakenly try `wp --require=test-cmd.php foo apple`
Then STDERR should be:
"""
Error: Invalid value specified for positional arg.
@@ -1047,24 +1126,23 @@ Feature: WP-CLI Commands
"""
bar
"""
- And STDERR should be empty
Scenario: WP-CLI suggests matching commands when user entry contains typos
Given a WP installation
- When I try `wp clu`
+ When I mistakenly try `wp clu`
Then STDERR should contain:
"""
Did you mean 'cli'?
"""
- When I try `wp cli nfo`
+ When I mistakenly try `wp cli nfo`
Then STDERR should contain:
"""
Did you mean 'info'?
"""
- When I try `wp cli beyondlevenshteinthreshold`
+ When I mistakenly try `wp cli beyondlevenshteinthreshold`
Then STDERR should not contain:
"""
Did you mean
@@ -1073,13 +1151,13 @@ Feature: WP-CLI Commands
Scenario: WP-CLI suggests matching parameters when user entry contains typos
Given an empty directory
- When I try `wp cli info --quie`
+ When I mistakenly try `wp cli info --quie`
Then STDERR should contain:
"""
Did you mean '--quiet'?
"""
- When I try `wp cli info --forma=json`
+ When I mistakenly try `wp cli info --forma=json`
Then STDERR should contain:
"""
Did you mean '--format'?
@@ -1098,7 +1176,7 @@ Feature: WP-CLI Commands
WP_CLI::add_command( 'test-command-2', function () {} );
"""
- When I try `wp --require=abort-add-command.php`
+ When I successfully try `wp --require=abort-add-command.php`
Then STDOUT should contain:
"""
test-command-1
@@ -1111,7 +1189,6 @@ Feature: WP-CLI Commands
"""
Warning: Aborting the addition of the command 'test-command-2' with reason: Testing hooks..
"""
- And the return code should be 0
Scenario: Adding a command can depend on a previous command having been added before
Given an empty directory
@@ -1192,28 +1269,24 @@ Feature: WP-CLI Commands
"""
test-command
"""
- And STDERR should be empty
When I run `wp help test-command`
Then STDOUT should contain:
"""
sub-command
"""
- And STDERR should be empty
When I run `wp test-command sub-command`
Then STDOUT should contain:
"""
Success: test-command sub-command
"""
- And STDERR should be empty
When I run `wp unknown-parent child-command`
Then STDOUT should contain:
"""
Success: unknown-parent child-command
"""
- And STDERR should be empty
Scenario: Command additions should work as must-use plugins
Given a WP installation
@@ -1241,28 +1314,24 @@ Feature: WP-CLI Commands
"""
test-command
"""
- And STDERR should be empty
When I run `wp help test-command`
Then STDOUT should contain:
"""
sub-command
"""
- And STDERR should be empty
When I run `wp test-command sub-command`
Then STDOUT should contain:
"""
Success: test-command sub-command
"""
- And STDERR should be empty
When I run `wp unknown-parent child-command`
Then STDOUT should contain:
"""
Success: unknown-parent child-command
"""
- And STDERR should be empty
Scenario: Command additions should work when registered on after_wp_load
Given a WP installation
@@ -1292,28 +1361,24 @@ Feature: WP-CLI Commands
"""
test-command
"""
- And STDERR should be empty
When I run `wp help test-command`
Then STDOUT should contain:
"""
sub-command
"""
- And STDERR should be empty
When I run `wp test-command sub-command`
Then STDOUT should contain:
"""
Success: test-command sub-command
"""
- And STDERR should be empty
When I run `wp unknown-parent child-command`
Then STDOUT should contain:
"""
Success: unknown-parent child-command
"""
- And STDERR should be empty
Scenario: The command should fire on `after_wp_load`
Given a WP installation
@@ -1347,21 +1412,18 @@ Feature: WP-CLI Commands
"""
bool(true)
"""
- And the return code should be 0
When I run `wp command before_wp_load`
Then STDOUT should contain:
"""
bool(false)
"""
- And the return code should be 0
- When I try `wp command after_wp_load --path=/tmp`
+ When I mistakenly try `wp command after_wp_load --path=/tmp`
Then STDERR should contain:
"""
Error: This does not seem to be a WordPress install.
"""
- And the return code should be 1
Scenario: The command should fire on `before_wp_load`
Given a WP installation
@@ -1392,20 +1454,16 @@ Feature: WP-CLI Commands
"""
When I run `wp command before_wp_load`
- Then STDERR should be empty
- And STDOUT should contain:
+ Then STDOUT should contain:
"""
bool(false)
"""
- And the return code should be 0
When I run `wp command after_wp_load`
- Then STDERR should be empty
- And STDOUT should contain:
+ Then STDOUT should contain:
"""
bool(true)
"""
- And the return code should be 0
Scenario: Command hook should fires as expected on __invoke()
Given a WP installation
@@ -1436,14 +1494,12 @@ Feature: WP-CLI Commands
"""
bool(true)
"""
- And the return code should be 0
- When I try `wp command --path=/tmp`
+ When I mistakenly try `wp command --path=/tmp`
Then STDERR should contain:
"""
Error: This does not seem to be a WordPress install.
"""
- And the return code should be 1
Scenario: Command namespaces can be added and are shown in help
Given an empty directory
@@ -1466,7 +1522,6 @@ Feature: WP-CLI Commands
"""
My Command Namespace Description.
"""
- And STDERR should be empty
Scenario: Command namespaces are only added when the command does not exist
Given an empty directory
@@ -1495,7 +1550,6 @@ Feature: WP-CLI Commands
"""
My Actual Namespaced Command.
"""
- And STDERR should be empty
Scenario: Command namespaces are replaced by commands of the same name
Given an empty directory
@@ -1524,7 +1578,6 @@ Feature: WP-CLI Commands
"""
My Actual Namespaced Command.
"""
- And STDERR should be empty
Scenario: Empty command namespaces show a notice when invoked
Given an empty directory
@@ -1543,7 +1596,6 @@ Feature: WP-CLI Commands
"""
The namespace my-namespaced-command does not contain any usable commands in the current context.
"""
- And STDERR should be empty
Scenario: Late-registered command should appear in command usage
Given a WP installation
diff --git a/features/config.feature b/features/config.feature
index e98e7a3008..54eb14d3a8 100644
--- a/features/config.feature
+++ b/features/config.feature
@@ -108,7 +108,7 @@ Feature: Have a config file
eval-file
"""
- When I try `WP_CLI_CONFIG_PATH=config.yml wp help eval-file`
+ When I mistakenly try `WP_CLI_CONFIG_PATH=config.yml wp help eval-file`
Then STDERR should be:
"""
Error: The 'eval-file' command has been disabled from the config file.
@@ -126,13 +126,13 @@ Feature: Have a config file
multisite-convert
"""
- When I try `WP_CLI_CONFIG_PATH=config.yml wp core multisite-convert`
+ When I mistakenly try `WP_CLI_CONFIG_PATH=config.yml wp core multisite-convert`
Then STDERR should contain:
"""
command has been disabled
"""
- When I try `WP_CLI_CONFIG_PATH=config.yml wp help core multisite-convert`
+ When I mistakenly try `WP_CLI_CONFIG_PATH=config.yml wp help core multisite-convert`
Then STDERR should contain:
"""
Error: The 'core multisite-convert' command has been disabled from the config file.
@@ -175,7 +175,7 @@ Feature: Have a config file
administrator
"""
- When I try `wp user create examplejane`
+ When I mistakenly try `wp user create examplejane`
Then STDERR should be:
"""
Error: Sorry, that email address is already used!
@@ -232,17 +232,17 @@ Feature: Have a config file
"""
When I run `WP_CLI_CONFIG_PATH=test-dir/config.yml wp help`
- Then STDERR should be empty
+ Then STDERR should be empty
Scenario: Load WordPress with `--debug`
Given a WP installation
- When I try `wp option get home --debug`
+ When I successfully try `wp option get home --debug`
Then STDERR should contain:
"""
No readable global config found
"""
- Then STDERR should contain:
+ And STDERR should contain:
"""
No project config found
"""
@@ -262,14 +262,13 @@ Feature: Have a config file
"""
Running command: option get
"""
- And the return code should be 0
- When I try `wp option get home --debug=bootstrap`
+ When I successfully try `wp option get home --debug=bootstrap`
Then STDERR should contain:
"""
No readable global config found
"""
- Then STDERR should contain:
+ And STDERR should contain:
"""
No project config found
"""
@@ -289,34 +288,12 @@ Feature: Have a config file
"""
Running command: option get
"""
- And the return code should be 0
- When I try `wp option get home --debug=foo`
- Then STDERR should not contain:
- """
- No readable global config found
- """
- Then STDERR should not contain:
- """
- No project config found
- """
- And STDERR should not contain:
- """
- Begin WordPress load
- """
- And STDERR should not contain:
- """
- wp-config.php path:
- """
- And STDERR should not contain:
- """
- Loaded WordPress
- """
- And STDERR should not contain:
+ When I run `wp option get home --debug=foo`
+ Then STDOUT should contain:
"""
- Running command: option get
+ http://example.com
"""
- And the return code should be 0
Scenario: Missing required files should not fatal WP-CLI
Given an empty directory
@@ -326,7 +303,7 @@ Feature: Have a config file
- missing-file.php
"""
- When I try `wp help`
+ When I mistakenly try `wp help`
Then STDERR should contain:
"""
Error: Required file 'missing-file.php' doesn't exist (from project's wp-cli.yml).
@@ -346,7 +323,7 @@ Feature: Have a config file
- /foo/baz.php
"""
- When I try `WP_CLI_CONFIG_PATH=config.yml wp help`
+ When I mistakenly try `WP_CLI_CONFIG_PATH=config.yml wp help`
Then STDERR should contain:
"""
Error: Required file 'baz.php' doesn't exist (from global config.yml).
@@ -355,7 +332,7 @@ Feature: Have a config file
Scenario: Missing required file as runtime argument
Given an empty directory
- When I try `wp help --require=foo.php`
+ When I mistakenly try `wp help --require=foo.php`
Then STDERR should contain:
"""
Error: Required file 'foo.php' doesn't exist (from runtime argument).
@@ -526,7 +503,7 @@ if ( !defined('ABSPATH') )
require_once(ABSPATH . 'wp-settings.php');
"""
- When I try `wp option get home`
+ When I mistakenly try `wp option get home`
Then STDERR should be:
"""
Error: Site 'example.dev/' not found. Verify DOMAIN_CURRENT_SITE matches an existing site or use `--url=` to override.
diff --git a/features/flags.feature b/features/flags.feature
index ce15bc9243..31bf7451ee 100644
--- a/features/flags.feature
+++ b/features/flags.feature
@@ -27,7 +27,7 @@ Feature: Global flags
Scenario: Invalid URL
Given a WP multisite installation
- When I try `wp post list --url=invalid.example.com`
+ When I mistakenly try `wp post list --url=invalid.example.com`
Then STDERR should be:
"""
Error: Site 'invalid.example.com' not found. Verify `--url=` matches an existing site.
@@ -36,9 +36,8 @@ Feature: Global flags
Scenario: Quiet run
Given a WP installation
- When I try `wp non-existing-command --quiet`
- Then the return code should be 1
- And STDERR should be:
+ When I mistakenly try `wp non-existing-command --quiet`
+ Then STDERR should be:
"""
Error: 'non-existing-command' is not a registered wp command. See 'wp help' for available commands.
"""
@@ -57,9 +56,8 @@ Feature: Global flags
"""
And the return code should be 0
- When I try `wp eval 'echo CONST_WITHOUT_QUOTES;' --debug`
- Then the return code should be 0
- And STDOUT should be:
+ When I successfully try `wp eval 'echo CONST_WITHOUT_QUOTES;' --debug`
+ Then STDOUT should be:
"""
CONST_WITHOUT_QUOTES
"""
@@ -89,9 +87,8 @@ Feature: Global flags
admin
"""
- When I try `wp --user=non-existing-user eval 'echo wp_get_current_user()->user_login;'`
- Then the return code should be 1
- And STDERR should be:
+ When I mistakenly try `wp --user=non-existing-user eval 'echo wp_get_current_user()->user_login;'`
+ Then STDERR should be:
"""
Error: Invalid user ID, email or login: 'non-existing-user'
"""
@@ -208,13 +205,13 @@ Feature: Global flags
Scenario: Enabling/disabling color
Given a WP installation
- When I try `wp --no-color non-existent-command`
+ When I mistakenly try `wp --no-color non-existent-command`
Then STDERR should be:
"""
Error: 'non-existent-command' is not a registered wp command. See 'wp help' for available commands.
"""
- When I try `wp --color non-existent-command`
+ When I mistakenly try `wp --color non-existent-command`
Then STDERR should contain:
"""
[31;1mError:
@@ -269,7 +266,7 @@ Feature: Global flags
Scenario: Using --http= requires wp-cli/restful
Given an empty directory
- When I try `wp --http=foo.dev`
+ When I mistakenly try `wp --http=foo.dev`
Then STDERR should be:
"""
Error: RESTful WP-CLI needs to be installed. Try 'wp package install wp-cli/restful'.
@@ -281,6 +278,7 @@ Feature: Global flags
"""
Running SSH command: ssh -q '' -T 'WP_CLI_STRICT_ARGS_MODE=1 wp
"""
+ And the return code should be 255
Scenario: SSH flag should support changing directories
When I try `wp --debug --ssh=wordpress:/my/path --version`
@@ -288,6 +286,7 @@ Feature: Global flags
"""
Running SSH command: ssh -q 'wordpress' -T 'cd '\''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/my/path'\''; wp
"""
+ And the return code should be 255
Scenario: SSH flag should support Docker
When I try `wp --debug --ssh=docker:user@wordpress --version`
@@ -295,3 +294,5 @@ Feature: Global flags
"""
Running SSH command: docker exec --user 'user' 'wordpress' sh -c
"""
+ And the return code should not be 0
+
diff --git a/features/framework.feature b/features/framework.feature
index 9908eb71ea..4557891625 100644
--- a/features/framework.feature
+++ b/features/framework.feature
@@ -83,6 +83,7 @@ Feature: Load WP-CLI
"""
Error: This does not seem to be a WordPress install.
"""
+ And the return code should be 1
Scenario: Globalize global variables in wp-config.php
Given an empty directory
@@ -159,7 +160,7 @@ Feature: Load WP-CLI
});
"""
- When I try `wp option get home`
+ When I successfully try `wp option get home`
Then STDERR should contain:
"""
Warning: Some code is trying to do a URL redirect.
@@ -184,17 +185,16 @@ Feature: Load WP-CLI
And a invalid-host.php file:
"""
` to override.
"""
- When I try `wp option get home --url=example.io`
+ When I mistakenly try `wp option get home --url=example.io`
Then STDERR should be:
"""
Error: Site 'example.io' not found. Verify `--url=` matches an existing site.
"""
Given "define( 'DOMAIN_CURRENT_SITE', 'example.org' );" replaced with " " in the wp-config.php file
+ # WP < 5.0 have bug which will not find a blog given an empty domain unless wp_blogs.domain empty which was (partly) addressed by https://core.trac.wordpress.org/ticket/42299
+ # So empty wp_blogs.domain to make behavior consistent across WP versions.
+ And I run `wp db query 'UPDATE wp_blogs SET domain = NULL'`
When I run `cat wp-config.php`
Then STDOUT should not contain:
@@ -334,13 +334,17 @@ Feature: Load WP-CLI
DOMAIN_CURRENT_SITE
"""
- When I try `wp option get home`
- Then STDERR should be:
+ # This will work as finds blog with empty domain and thus uses `home` option.
+ When I run `wp option get home`
+ Then STDOUT should be:
"""
- Error: Site not found. Define DOMAIN_CURRENT_SITE in 'wp-config.php' or use `--url=` to override.
+ http://example.com
"""
- When I try `wp option get home --url=example.io`
+ # Undo above.
+ Given I run `wp db query 'UPDATE wp_blogs SET domain = "example.com"'`
+
+ When I mistakenly try `wp option get home --url=example.io`
Then STDERR should be:
"""
Error: Site 'example.io' not found. Verify `--url=` matches an existing site.
diff --git a/features/help.feature b/features/help.feature
index 74753b28f9..260951edf3 100644
--- a/features/help.feature
+++ b/features/help.feature
@@ -9,42 +9,36 @@ Feature: Get help about WP-CLI commands
Run 'wp help ' to get more information on a specific command.
"""
- And STDERR should be empty
When I run `wp help core`
Then STDOUT should contain:
"""
wp core
"""
- And STDERR should be empty
When I run `wp help core download`
Then STDOUT should contain:
"""
wp core download
"""
- And STDERR should be empty
When I run `wp help help`
Then STDOUT should contain:
"""
wp help
"""
- And STDERR should be empty
When I run `wp help help`
Then STDOUT should contain:
"""
GLOBAL PARAMETERS
"""
- And STDERR should be empty
When I run `wp post list --post_type=post --posts_per_page=5 --help`
Then STDOUT should contain:
"""
wp post list
"""
- And STDERR should be empty
# Prior to WP 4.3 widgets & others used PHP 4 style constructors and prior to WP 3.9 wpdb used the mysql extension which can all lead (depending on PHP version) to PHP Deprecated notices.
@require-wp-4.3
@@ -57,36 +51,33 @@ Feature: Get help about WP-CLI commands
Run 'wp help ' to get more information on a specific command.
"""
- And STDERR should be empty
When I run `wp help core`
Then STDOUT should contain:
"""
wp core
"""
- And STDERR should be empty
When I run `wp help core download`
Then STDOUT should contain:
"""
wp core download
"""
- And STDERR should be empty
When I run `wp help help`
Then STDOUT should contain:
"""
wp help
"""
- And STDERR should be empty
When I run `wp help help`
Then STDOUT should contain:
"""
GLOBAL PARAMETERS
"""
- And STDERR should be empty
+ # Fixed in trunk, WP isn't compatible with PHP 7.2 due to `__autoload()` in "wp-includes/compat.php".
+ @less-than-php-7.2
Scenario: Help when WordPress is downloaded but not installed
Given an empty directory
@@ -96,7 +87,6 @@ Feature: Get help about WP-CLI commands
"""
wp config create
"""
- And STDERR should be empty
When I run `wp config create {CORE_CONFIG_SETTINGS}`
And I run `wp help core install`
@@ -104,44 +94,37 @@ Feature: Get help about WP-CLI commands
"""
wp core install
"""
- And STDERR should be empty
When I run `wp help core is-installed`
Then STDOUT should contain:
"""
wp core is-installed
"""
- And STDERR should be empty
When I run `wp help core`
Then STDOUT should contain:
"""
wp core
"""
- And STDERR should be empty
When I run `wp help config`
Then STDOUT should contain:
"""
wp config
"""
- And STDERR should be empty
When I run `wp help db`
Then STDOUT should contain:
"""
wp db
"""
- And STDERR should be empty
- When I try `wp help non-existent-command`
- Then the return code should be 1
- And STDERR should be:
+ When I mistakenly try `wp help non-existent-command`
+ Then STDERR should be:
"""
Warning: Can’t select database. We were able to connect to the database server (which means your username and password is okay) but not able to select the `wp_cli_test` database.
Error: 'non-existent-command' is not a registered wp command. See 'wp help' for available commands.
"""
- And STDOUT should be empty
# Bug: if `WP_DEBUG` (or `WP_DEBUG_DISPLAY') is defined falsey than a db error won't be trapped.
Given a define-wp-debug-false.php file:
@@ -149,192 +132,154 @@ Feature: Get help about WP-CLI commands
run 'eval "echo wp_get_current_user()->user_login . PHP_EOL;"'`
Then STDOUT should be:
@@ -62,8 +60,6 @@ Feature: Run a WP-CLI command
admin
returned: NULL
"""
- And STDERR should be empty
- And the return code should be 0
When I run `WP_CLI_CONFIG_PATH=config.yml wp run 'user get'`
Then STDOUT should be:
@@ -71,8 +67,6 @@ Feature: Run a WP-CLI command
admin@example.com
returned: NULL
"""
- And STDERR should be empty
- And the return code should be 0
Examples:
| flag |
@@ -87,32 +81,24 @@ Feature: Run a WP-CLI command
"""
returned: 'http://example.com'
"""
- And STDERR should be empty
- And the return code should be 0
When I run `wp --return run 'eval "echo wp_get_current_user()->user_login . PHP_EOL;"'`
Then STDOUT should be:
"""
returned: 'admin'
"""
- And STDERR should be empty
- And the return code should be 0
When I run `wp --return=stderr run 'eval "echo wp_get_current_user()->user_login . PHP_EOL;"'`
Then STDOUT should be:
"""
returned: ''
"""
- And STDERR should be empty
- And the return code should be 0
When I run `wp --return=return_code run 'eval "echo wp_get_current_user()->user_login . PHP_EOL;"'`
Then STDOUT should be:
"""
returned: 0
"""
- And STDERR should be empty
- And the return code should be 0
When I run `wp --return=all run 'eval "echo wp_get_current_user()->user_login . PHP_EOL;"'`
Then STDOUT should be:
@@ -123,16 +109,12 @@ Feature: Run a WP-CLI command
'return_code' => 0,
)
"""
- And STDERR should be empty
- And the return code should be 0
When I run `WP_CLI_CONFIG_PATH=config.yml wp --return run 'user get'`
Then STDOUT should be:
"""
returned: 'admin@example.com'
"""
- And STDERR should be empty
- And the return code should be 0
Examples:
| flag |
@@ -159,13 +141,11 @@ Feature: Run a WP-CLI command
Scenario Outline: Exit on error by default
Given a WP installation
- When I try `wp run 'eval "WP_CLI::error( var_export( get_current_user_id(), true ) );"'`
- Then STDOUT should be empty
- And STDERR should be:
+ When I mistakenly try `wp run 'eval "WP_CLI::error( var_export( get_current_user_id(), true ) );"'`
+ Then STDERR should be:
"""
Error: 1
"""
- And the return code should be 1
Examples:
| flag |
@@ -175,7 +155,7 @@ Feature: Run a WP-CLI command
Scenario Outline: Override erroring on exit
Given a WP installation
- When I try `wp run --no-exit_error --return=all 'eval "WP_CLI::error( var_export( get_current_user_id(), true ) );"'`
+ When I run `wp run --no-exit_error --return=all 'eval "WP_CLI::error( var_export( get_current_user_id(), true ) );"'`
Then STDOUT should be:
"""
returned: array (
@@ -184,16 +164,12 @@ Feature: Run a WP-CLI command
'return_code' => 1,
)
"""
- And STDERR should be empty
- And the return code should be 0
When I run `wp --no-exit_error run 'option pluck foo$bar barfoo'`
Then STDOUT should be:
"""
returned: NULL
"""
- And STDERR should be empty
- And the return code should be 0
Examples:
| flag |
@@ -214,8 +190,6 @@ Feature: Run a WP-CLI command
'return_code' => 1,
)
"""
- And STDERR should be empty
- And the return code should be 0
When I run `wp run --no-exit_error --return=all 'eval "echo '\'echo\''; WP_CLI::log( '\'log\'' ); WP_CLI::warning( '\'warning\''); WP_CLI::success( '\'success\'' );"'`
Then STDOUT should be:
@@ -227,8 +201,6 @@ Feature: Run a WP-CLI command
'return_code' => 0,
)
"""
- And STDERR should be empty
- And the return code should be 0
Examples:
| flag |
@@ -237,16 +209,13 @@ Feature: Run a WP-CLI command
Scenario Outline: Installed packages work as expected
Given a WP installation
-
- When I run `wp package install wp-cli/scaffold-package-command`
- Then STDERR should be empty
+ And I run `wp package install wp-cli/scaffold-package-command`
When I run `wp run 'help scaffold package'`
Then STDOUT should contain:
"""
wp scaffold package
"""
- And STDERR should be empty
Examples:
| flag |
@@ -263,8 +232,6 @@ Feature: Run a WP-CLI command
Success: Rewrite structure set.
returned: NULL
"""
- And STDERR should be empty
- And the return code should be 0
Examples:
| flag |
@@ -280,8 +247,6 @@ Feature: Run a WP-CLI command
http://example.com/?cat=1
returned: NULL
"""
- And STDERR should be empty
- And the return code should be 0
Examples:
| flag |
diff --git a/features/runner.feature b/features/runner.feature
index 4fcb5ae506..22f6bd7459 100644
--- a/features/runner.feature
+++ b/features/runner.feature
@@ -1,21 +1,22 @@
Feature: Runner WP-CLI
Scenario: Path argument should be slashed correctly
- When I try `wp no-such-command --path=/foo --debug`
+ When I mistakenly try `wp no-such-command --path=/foo --debug`
Then STDERR should contain:
"""
ABSPATH defined: /foo/
"""
- When I try `wp no-such-command --path=/foo/ --debug`
+ When I mistakenly try `wp no-such-command --path=/foo/ --debug`
Then STDERR should contain:
"""
ABSPATH defined: /foo/
"""
- When I try `wp no-such-command --path=/foo\\ --debug`
+ When I mistakenly try `wp no-such-command --path=/foo\\ --debug`
Then STDERR should contain:
"""
ABSPATH defined: /foo/
"""
+ And the return code should be 1
diff --git a/features/skip-plugins.feature b/features/skip-plugins.feature
index 4337496286..07c9c23502 100644
--- a/features/skip-plugins.feature
+++ b/features/skip-plugins.feature
@@ -37,6 +37,7 @@ Feature: Skipping plugins
"""
Call to undefined function hello_dolly()
"""
+ And the return code should be 255
# No plugins should be loaded when --skip-plugins doesn't have a value
When I run `wp --skip-plugins eval 'var_export( defined("AKISMET_VERSION") );var_export( function_exists( "hello_dolly" ) );'`
@@ -60,6 +61,7 @@ Feature: Skipping plugins
"""
Call to undefined function hello_dolly()
"""
+ And the return code should be 255
Scenario: Skipping all plugins via config file
Given a WP installation
@@ -74,11 +76,12 @@ Feature: Skipping plugins
"""
Call to undefined function hello_dolly()
"""
+ And the return code should be 255
Scenario: Skip network active plugins
Given a WP multisite installation
- When I try `wp plugin deactivate akismet hello`
+ When I successfully try `wp plugin deactivate akismet hello`
Then STDERR should be:
"""
Warning: Plugin 'akismet' isn't active.
@@ -88,7 +91,6 @@ Feature: Skipping plugins
"""
Success: Plugins already deactivated.
"""
- And the return code should be 0
When I run `wp plugin activate --network akismet hello`
And I run `wp eval 'var_export( defined("AKISMET_VERSION") );var_export( function_exists( "hello_dolly" ) );'`
diff --git a/features/skip-themes.feature b/features/skip-themes.feature
index eb54988ce0..d1aa365a14 100644
--- a/features/skip-themes.feature
+++ b/features/skip-themes.feature
@@ -1,118 +1,111 @@
Feature: Skipping themes
+ Background:
+ Given download:
+ | path | url |
+ | {CACHE_DIR}/classic.1.6.zip | https://downloads.wordpress.org/theme/classic.1.6.zip |
+ | {CACHE_DIR}/espied.1.2.2.zip | https://downloads.wordpress.org/theme/espied.1.2.2.zip |
+ | {CACHE_DIR}/sidespied.1.0.3.zip | https://downloads.wordpress.org/theme/sidespied.1.0.3.zip |
+
Scenario: Skipping themes via global flag
Given a WP installation
- And I run `wp theme install classic`
- And I run `wp theme install default --activate`
+ And I run `wp theme install {CACHE_DIR}/classic.1.6.zip`
+ And I run `wp theme install {CACHE_DIR}/espied.1.2.2.zip --activate`
- When I run `wp eval 'var_export( function_exists( "kubrick_head" ) );'`
+ When I run `wp eval 'var_export( function_exists( "espied_scripts" ) );'`
Then STDOUT should be:
"""
true
"""
- And STDERR should be empty
# The specified theme should be skipped
- When I run `wp --skip-themes=default eval 'var_export( function_exists( "kubrick_head" ) );'`
+ When I run `wp --skip-themes=espied eval 'var_export( function_exists( "espied_scripts" ) );'`
Then STDOUT should be:
"""
false
"""
- And STDERR should be empty
# All themes should be skipped
- When I run `wp --skip-themes eval 'var_export( function_exists( "kubrick_head" ) );'`
+ When I run `wp --skip-themes eval 'var_export( function_exists( "espied_scripts" ) );'`
Then STDOUT should be:
"""
false
"""
- And STDERR should be empty
# Skip another theme
- When I run `wp --skip-themes=classic eval 'var_export( function_exists( "kubrick_head" ) );'`
+ When I run `wp --skip-themes=classic eval 'var_export( function_exists( "espied_scripts" ) );'`
Then STDOUT should be:
"""
true
"""
- And STDERR should be empty
# The specified theme should still show up as an active theme
- When I run `wp --skip-themes theme status default`
+ When I run `wp --skip-themes theme status espied`
Then STDOUT should contain:
"""
Active
"""
- And STDERR should be empty
# Skip several themes
- When I run `wp --skip-themes=classic,default eval 'var_export( function_exists( "kubrick_head" ) );'`
+ When I run `wp --skip-themes=classic,espied eval 'var_export( function_exists( "espied_scripts" ) );'`
Then STDOUT should be:
"""
false
"""
- And STDERR should be empty
Scenario: Skip parent and child themes
Given a WP installation
- And I run `wp theme install jolene biker`
+ And I run `wp theme install {CACHE_DIR}/espied.1.2.2.zip {CACHE_DIR}/sidespied.1.0.3.zip`
- When I run `wp theme activate jolene`
- When I run `wp eval 'var_export( function_exists( "jolene_setup" ) );'`
+ When I run `wp theme activate espied`
+ When I run `wp eval 'var_export( function_exists( "espied_scripts" ) );'`
Then STDOUT should be:
"""
true
"""
- And STDERR should be empty
- When I run `wp --skip-themes=jolene eval 'var_export( function_exists( "jolene_setup" ) );'`
+ When I run `wp --skip-themes=espied eval 'var_export( function_exists( "espied_scripts" ) );'`
Then STDOUT should be:
"""
false
"""
- And STDERR should be empty
- When I run `wp theme activate biker`
- When I run `wp eval 'var_export( function_exists( "jolene_setup" ) );'`
+ When I run `wp theme activate sidespied`
+ When I run `wp eval 'var_export( function_exists( "espied_scripts" ) );'`
Then STDOUT should be:
"""
true
"""
- And STDERR should be empty
- When I run `wp eval 'var_export( function_exists( "biker_setup" ) );'`
+ When I run `wp eval 'var_export( function_exists( "sidespied_scripts" ) );'`
Then STDOUT should be:
"""
true
"""
- And STDERR should be empty
- When I run `wp --skip-themes=biker eval 'var_export( function_exists( "jolene_setup" ) );'`
+ When I run `wp --skip-themes=sidespied eval 'var_export( function_exists( "espied_scripts" ) );'`
Then STDOUT should be:
"""
false
"""
- And STDERR should be empty
- When I run `wp --skip-themes=biker eval 'var_export( function_exists( "biker_setup" ) );'`
+ When I run `wp --skip-themes=sidespied eval 'var_export( function_exists( "sidespied_scripts" ) );'`
Then STDOUT should be:
"""
false
"""
- And STDERR should be empty
- When I run `wp --skip-themes=biker eval 'echo get_template_directory();'`
+ When I run `wp --skip-themes=sidespied eval 'echo get_template_directory();'`
Then STDOUT should contain:
"""
- wp-content/themes/jolene
+ wp-content/themes/espied
"""
- And STDERR should be empty
- When I run `wp --skip-themes=biker eval 'echo get_stylesheet_directory();'`
+ When I run `wp --skip-themes=sidespied eval 'echo get_stylesheet_directory();'`
Then STDOUT should contain:
"""
- wp-content/themes/biker
+ wp-content/themes/sidespied
"""
- And STDERR should be empty
Scenario: Skipping multiple themes via config file
Given a WP installation
@@ -120,10 +113,10 @@ Feature: Skipping themes
"""
skip-themes:
- classic
- - default
+ - espied
"""
- And I run `wp theme install classic --activate`
- And I run `wp theme install default`
+ And I run `wp theme install {CACHE_DIR}/classic.1.6.zip --activate`
+ And I run `wp theme install {CACHE_DIR}/espied.1.2.2.zip`
# The classic theme should show up as an active theme
When I run `wp theme status`
@@ -131,22 +124,19 @@ Feature: Skipping themes
"""
A classic
"""
- And STDERR should be empty
- # The default theme should show up as an installed theme
+ # The espied theme should show up as an installed theme
When I run `wp theme status`
Then STDOUT should contain:
"""
- I default
+ I espied
"""
- And STDERR should be empty
- And I run `wp theme activate default`
+ And I run `wp theme activate espied`
- # The default theme should be skipped
- When I run `wp eval 'var_export( function_exists( "kubrick_head" ) );'`
+ # The espied theme should be skipped
+ When I run `wp eval 'var_export( function_exists( "espied_scripts" ) );'`
Then STDOUT should be:
"""
false
"""
- And STDERR should be empty
diff --git a/features/steps/given.php b/features/steps/given.php
index 3e501c2c7d..c0b00707fb 100644
--- a/features/steps/given.php
+++ b/features/steps/given.php
@@ -35,12 +35,18 @@ function ( $world ) {
$steps->Given( '/^an? ([^\s]+) file:$/',
function ( $world, $path, PyStringNode $content ) {
$content = (string) $content . "\n";
- $full_path = $world->variables['RUN_DIR'] . "/$path";
- $dir = dirname( $full_path );
+ $path = $world->replace_variables( $path );
+ if ( ! WP_CLI\Utils\is_path_absolute( $path ) ) {
+ $path = $world->variables['RUN_DIR'] . "/$path";
+ }
+ if ( 0 !== strpos( $path, sys_get_temp_dir() ) ) {
+ throw new RuntimeException( sprintf( "Attempted to create a file '%s' that is not in the temp directory '%s'. " . __FILE__ . ':' . __LINE__, $path, sys_get_temp_dir() ) );
+ }
+ $dir = dirname( $path );
if ( ! file_exists( $dir ) ) {
mkdir( $dir, 0777, true /*recursive*/ );
}
- file_put_contents( $full_path, $content );
+ file_put_contents( $path, $content );
}
);
@@ -69,31 +75,31 @@ function ( $world ) {
}
);
-$steps->Given( '/^a WP (install|installation)$/',
+$steps->Given( '/^a WP install(?:ation)?$/',
function ( $world ) {
$world->install_wp();
}
);
-$steps->Given( "/^a WP (install|installation) in '([^\s]+)'$/",
- function ( $world, $_, $subdir ) {
+$steps->Given( "/^a WP install(?:ation)? in '([^\s]+)'$/",
+ function ( $world, $subdir ) {
$world->install_wp( $subdir );
}
);
-$steps->Given( '/^a WP (install|installation) with Composer$/',
+$steps->Given( '/^a WP install(?:ation)? with Composer$/',
function ( $world ) {
$world->install_wp_with_composer();
}
);
-$steps->Given( "/^a WP (install|installation) with Composer and a custom vendor directory '([^\s]+)'$/",
- function ( $world, $_, $vendor_directory ) {
+$steps->Given( "/^a WP install(?:ation)? with Composer and a custom vendor directory '([^\s]+)'$/",
+ function ( $world, $vendor_directory ) {
$world->install_wp_with_composer( $vendor_directory );
}
);
-$steps->Given( '/^a WP multisite (subdirectory|subdomain)?\s?(install|installation)$/',
+$steps->Given( '/^a WP multisite (subdirectory|subdomain)?\s?install(?:ation)?$/',
function ( $world, $type = 'subdirectory' ) {
$world->install_wp();
$subdomains = ! empty( $type ) && 'subdomain' === $type ? 1 : 0;
@@ -158,9 +164,9 @@ function ( $world, $stream, $output_filter, $key ) {
}
);
-$steps->Given( '/^a new Phar with (?:the same version|version "([^"]+)")$/',
- function ( $world, $version = 'same' ) {
- $world->build_phar( $version );
+$steps->Given( '/^a new Phar with (?:the same version|version "([^"]+)")(?: and (cli) build)?$/',
+ function ( $world, $version = 'same', $build = '' ) {
+ $world->build_phar( $version, $build );
}
);
diff --git a/features/steps/when.php b/features/steps/when.php
index d23aa0e669..d60216407c 100644
--- a/features/steps/when.php
+++ b/features/steps/when.php
@@ -2,16 +2,19 @@
use Behat\Gherkin\Node\PyStringNode,
Behat\Gherkin\Node\TableNode,
- WP_CLI\Process;
+ WP_CLI\Process,
+ WP_CLI\Utils;
function invoke_proc( $proc, $mode ) {
$map = array(
- 'run' => 'run_check_stderr',
- 'try' => 'run'
+ 'run' => array( 0, true, null ),
+ 'try' => array( null, null, null ),
+ 'mistakenly try' => array( 1, false, true ),
+ 'successfully try' => array( 0, false, false ),
);
- $method = $map[ $mode ];
+ $args = $map[ $mode ];
- return $proc->$method();
+ return $proc->run_check_args( $args[0] /*return_code*/, $args[1] /*stderr_empty*/, $args[2] /*stdout_empty*/ );
}
function capture_email_sends( $stdout ) {
@@ -25,9 +28,12 @@ function ( $world, $cmd ) {
}
);
-$steps->When( '/^I (run|try) `([^`]+)`$/',
- function ( $world, $mode, $cmd ) {
+$steps->When( '/^I (run|try|mistakenly try|successfully try) `([^`]+)`$/',
+ function ( $world, $mode, $cmd, $return_code = 0, $stdout_empty = '' ) {
$cmd = $world->replace_variables( $cmd );
+ if ( Utils\is_windows() ) {
+ $cmd = _wp_cli_esc_cmd_win( $cmd );
+ }
$world->result = invoke_proc( $world->proc( $cmd ), $mode );
list( $world->result->stdout, $world->email_sends ) = capture_email_sends( $world->result->stdout );
}
@@ -36,6 +42,9 @@ function ( $world, $mode, $cmd ) {
$steps->When( "/^I (run|try) `([^`]+)` from '([^\s]+)'$/",
function ( $world, $mode, $cmd, $subdir ) {
$cmd = $world->replace_variables( $cmd );
+ if ( Utils\is_windows() ) {
+ $cmd = _wp_cli_esc_cmd_win( $cmd );
+ }
$world->result = invoke_proc( $world->proc( $cmd, array(), $subdir ), $mode );
list( $world->result->stdout, $world->email_sends ) = capture_email_sends( $world->result->stdout );
}
diff --git a/features/utils-wp.feature b/features/utils-wp.feature
new file mode 100644
index 0000000000..c71ddb903a
--- /dev/null
+++ b/features/utils-wp.feature
@@ -0,0 +1,734 @@
+Feature: Utilities that depend on WordPress code
+
+ Scenario: Clear WP cache
+ Given a WP install
+ And a test.php file:
+ """
+ cache ) . ',' . isset( $wp_object_cache->group_ops ) . ',' . isset( $wp_object_cache->stats ) . ',' . isset( $wp_object_cache->memcache_debug ) . "\n";
+ WP_CLI\Utils\wp_clear_object_cache();
+ echo empty( $wp_object_cache->cache ) . ',' . isset( $wp_object_cache->group_ops ) . ',' . isset( $wp_object_cache->stats ) . ',' . isset( $wp_object_cache->memcache_debug ) . "\n";
+ } );
+ """
+
+ When I run `wp post create --post_title="Foo Bar" --porcelain`
+ And I run `wp --require=test.php eval ''`
+ Then STDOUT should be:
+ """
+ ,,,
+ 1,,,
+ """
+
+ Scenario: Get WP table names for single site install
+ Given a WP install
+ And I run `wp db query "CREATE TABLE xx_wp_posts ( id int );"`
+ And I run `wp db query "CREATE TABLE wp_xx_posts ( id int );"`
+ And I run `wp db query "CREATE TABLE wp_posts_xx ( id int );"`
+ And I run `wp db query "CREATE TABLE wp_categories ( id int );"`
+ And a table_names.php file:
+ """
+ ...]
+ * : List tables based on wildcard search, e.g. 'wp_*_options' or 'wp_post?'.
+ *
+ * [--scope=]
+ * : Can be all, global, ms_global, blog, or old tables. Defaults to all.
+ *
+ * [--network]
+ * : List all the tables in a multisite install. Overrides --scope=.
+ *
+ * [--all-tables-with-prefix]
+ * : List all tables that match the table prefix even if not registered on $wpdb. Overrides --network.
+ *
+ * [--all-tables]
+ * : List all tables in the database, regardless of the prefix, and even if not registered on $wpdb. Overrides --all-tables-with-prefix.
+ */
+ function test_wp_get_table_names( $args, $assoc_args ) {
+ if ( $tables = WP_CLI\Utils\wp_get_table_names( $args, $assoc_args ) ) {
+ echo implode( PHP_EOL, $tables ) . PHP_EOL;
+ }
+ }
+ WP_CLI::add_command( 'get_table_names', 'test_wp_get_table_names' );
+ """
+
+ When I run `wp --require=table_names.php get_table_names`
+ Then STDOUT should contain:
+ """
+ wp_commentmeta
+ wp_comments
+ wp_links
+ wp_options
+ wp_postmeta
+ wp_posts
+ wp_term_relationships
+ wp_term_taxonomy
+ """
+ # Leave out wp_termmeta for old WP compat.
+ And STDOUT should contain:
+ """
+ wp_terms
+ wp_usermeta
+ wp_users
+ """
+ And save STDOUT as {DEFAULT_STDOUT}
+
+ When I run `wp --require=table_names.php get_table_names --scope=all`
+ Then STDOUT should be:
+ """
+ {DEFAULT_STDOUT}
+ """
+
+ When I run `wp --require=table_names.php get_table_names --scope=blog`
+ Then STDOUT should contain:
+ """
+ wp_commentmeta
+ wp_comments
+ wp_links
+ wp_options
+ wp_postmeta
+ wp_posts
+ wp_term_relationships
+ wp_term_taxonomy
+ """
+ # Leave out wp_termmeta for old WP compat.
+ And STDOUT should contain:
+ """
+ wp_terms
+ """
+
+ When I run `wp --require=table_names.php get_table_names --scope=global`
+ Then STDOUT should be:
+ """
+ wp_usermeta
+ wp_users
+ """
+
+ When I run `wp --require=table_names.php get_table_names --scope=ms_global`
+ Then STDOUT should be empty
+
+ When I run `wp --require=table_names.php get_table_names --scope=old`
+ Then STDOUT should be:
+ """
+ wp_categories
+ """
+
+ When I run `wp --require=table_names.php get_table_names --network`
+ Then STDOUT should be:
+ """
+ {DEFAULT_STDOUT}
+ """
+
+ When I run `wp --require=table_names.php get_table_names --all-tables-with-prefix`
+ Then STDOUT should contain:
+ """
+ wp_categories
+ wp_commentmeta
+ wp_comments
+ wp_links
+ wp_options
+ wp_postmeta
+ wp_posts
+ wp_posts_xx
+ wp_term_relationships
+ wp_term_taxonomy
+ """
+ # Leave out wp_termmeta for old WP compat.
+ And STDOUT should contain:
+ """
+ wp_terms
+ wp_usermeta
+ wp_users
+ wp_xx_posts
+ """
+
+ When I run `wp --require=table_names.php get_table_names --all-tables`
+ Then STDOUT should contain:
+ """
+ wp_categories
+ wp_commentmeta
+ wp_comments
+ wp_links
+ wp_options
+ wp_postmeta
+ wp_posts
+ wp_posts_xx
+ wp_term_relationships
+ wp_term_taxonomy
+ """
+ # Leave out wp_termmeta for old WP compat.
+ And STDOUT should contain:
+ """
+ wp_terms
+ wp_usermeta
+ wp_users
+ wp_xx_posts
+ xx_wp_posts
+ """
+
+ When I run `wp --require=table_names.php get_table_names '*_posts'`
+ Then STDOUT should be:
+ """
+ wp_posts
+ """
+
+ When I run `wp --require=table_names.php get_table_names 'wp_post*'`
+ Then STDOUT should be:
+ """
+ wp_postmeta
+ wp_posts
+ """
+
+ When I run `wp --require=table_names.php get_table_names 'wp*osts'`
+ Then STDOUT should be:
+ """
+ wp_posts
+ """
+
+ When I run `wp --require=table_names.php get_table_names '*_posts' --scope=blog`
+ Then STDOUT should be:
+ """
+ wp_posts
+ """
+
+ When I try `wp --require=table_names.php get_table_names '*_posts' --scope=global`
+ Then STDERR should be:
+ """
+ Error: Couldn't find any tables matching: *_posts
+ """
+ And STDOUT should be empty
+
+ When I run `wp --require=table_names.php get_table_names '*_posts' --network`
+ Then STDOUT should be:
+ """
+ wp_posts
+ """
+
+ When I run `wp --require=table_names.php get_table_names '*_posts' --all-tables-with-prefix`
+ Then STDOUT should be:
+ """
+ wp_posts
+ wp_xx_posts
+ """
+
+ When I run `wp --require=table_names.php get_table_names '*wp_posts' --all-tables-with-prefix`
+ Then STDOUT should be:
+ """
+ wp_posts
+ """
+
+ When I run `wp --require=table_names.php get_table_names 'wp_post*' --all-tables-with-prefix`
+ Then STDOUT should be:
+ """
+ wp_postmeta
+ wp_posts
+ wp_posts_xx
+ """
+
+ When I run `wp --require=table_names.php get_table_names 'wp*osts' --all-tables-with-prefix`
+ Then STDOUT should be:
+ """
+ wp_posts
+ wp_xx_posts
+ """
+
+ When I run `wp --require=table_names.php get_table_names '*_posts' --all-tables`
+ Then STDOUT should be:
+ """
+ wp_posts
+ wp_xx_posts
+ xx_wp_posts
+ """
+
+ When I run `wp --require=table_names.php get_table_names '*wp_posts' --all-tables`
+ Then STDOUT should be:
+ """
+ wp_posts
+ xx_wp_posts
+ """
+
+ When I run `wp --require=table_names.php get_table_names 'wp_post*' --all-tables`
+ Then STDOUT should be:
+ """
+ wp_postmeta
+ wp_posts
+ wp_posts_xx
+ """
+
+ When I run `wp --require=table_names.php get_table_names 'wp*osts' --all-tables`
+ Then STDOUT should be:
+ """
+ wp_posts
+ wp_xx_posts
+ """
+
+ When I try `wp --require=table_names.php get_table_names non_existent_table`
+ Then STDERR should be:
+ """
+ Error: Couldn't find any tables matching: non_existent_table
+ """
+ And STDOUT should be empty
+
+ When I run `wp --require=table_names.php get_table_names wp_posts non_existent_table`
+ Then STDOUT should be:
+ """
+ wp_posts
+ """
+
+ When I run `wp --require=table_names.php get_table_names wp_posts non_existent_table 'wp_?ption*'`
+ Then STDOUT should be:
+ """
+ wp_options
+ wp_posts
+ """
+
+ Scenario: Get WP table names for multisite install
+ Given a WP multisite install
+ And I run `wp db query "CREATE TABLE xx_wp_posts ( id int );"`
+ And I run `wp db query "CREATE TABLE xx_wp_2_posts ( id int );"`
+ And I run `wp db query "CREATE TABLE wp_xx_posts ( id int );"`
+ And I run `wp db query "CREATE TABLE wp_2_xx_posts ( id int );"`
+ And I run `wp db query "CREATE TABLE wp_posts_xx ( id int );"`
+ And I run `wp db query "CREATE TABLE wp_2_posts_xx ( id int );"`
+ And I run `wp db query "CREATE TABLE wp_categories ( id int );"`
+ And I run `wp db query "CREATE TABLE wp_sitecategories ( id int );"`
+ And a table_names.php file:
+ """
+ ...]
+ * : List tables based on wildcard search, e.g. 'wp_*_options' or 'wp_post?'.
+ *
+ * [--scope=]
+ * : Can be all, global, ms_global, blog, or old tables. Defaults to all.
+ *
+ * [--network]
+ * : List all the tables in a multisite install. Overrides --scope=.
+ *
+ * [--all-tables-with-prefix]
+ * : List all tables that match the table prefix even if not registered on $wpdb. Overrides --network.
+ *
+ * [--all-tables]
+ * : List all tables in the database, regardless of the prefix, and even if not registered on $wpdb. Overrides --all-tables-with-prefix.
+ */
+ function test_wp_get_table_names( $args, $assoc_args ) {
+ if ( $tables = WP_CLI\Utils\wp_get_table_names( $args, $assoc_args ) ) {
+ echo implode( PHP_EOL, $tables ) . PHP_EOL;
+ }
+ }
+ WP_CLI::add_command( 'get_table_names', 'test_wp_get_table_names' );
+ """
+
+ # With no subsite.
+ When I run `wp --require=table_names.php get_table_names`
+ Then STDOUT should contain:
+ """
+ wp_blog_versions
+ wp_blogs
+ wp_commentmeta
+ wp_comments
+ wp_links
+ wp_options
+ wp_postmeta
+ wp_posts
+ wp_registration_log
+ wp_signups
+ wp_site
+ wp_sitemeta
+ wp_term_relationships
+ wp_term_taxonomy
+ """
+ # Leave out wp_termmeta for old WP compat.
+ And STDOUT should contain:
+ """
+ wp_terms
+ wp_usermeta
+ wp_users
+ """
+ And save STDOUT as {DEFAULT_STDOUT}
+
+ When I run `wp --require=table_names.php get_table_names --scope=all`
+ Then STDOUT should be:
+ """
+ {DEFAULT_STDOUT}
+ """
+
+ When I run `wp --require=table_names.php get_table_names --scope=blog`
+ Then STDOUT should contain:
+ """
+ wp_commentmeta
+ wp_comments
+ wp_links
+ wp_options
+ wp_postmeta
+ wp_posts
+ wp_term_relationships
+ wp_term_taxonomy
+ """
+ # Leave out wp_termmeta for old WP compat.
+ And STDOUT should contain:
+ """
+ wp_terms
+ """
+
+ When I run `wp --require=table_names.php get_table_names --scope=global`
+ Then STDOUT should be:
+ """
+ wp_blog_versions
+ wp_blogs
+ wp_registration_log
+ wp_signups
+ wp_site
+ wp_sitemeta
+ wp_usermeta
+ wp_users
+ """
+ And save STDOUT as {GLOBAL_STDOUT}
+
+ When I run `wp --require=table_names.php get_table_names --scope=ms_global`
+ Then STDOUT should be:
+ """
+ wp_blog_versions
+ wp_blogs
+ wp_registration_log
+ wp_signups
+ wp_site
+ wp_sitemeta
+ """
+
+ When I run `wp --require=table_names.php get_table_names --scope=old`
+ Then STDOUT should be:
+ """
+ wp_categories
+ """
+
+ When I run `wp --require=table_names.php get_table_names --network`
+ Then STDOUT should be:
+ """
+ {DEFAULT_STDOUT}
+ """
+
+ # With subsite.
+ Given I run `wp site create --slug=foo`
+ When I run `wp --require=table_names.php get_table_names`
+ Then STDOUT should be:
+ """
+ {DEFAULT_STDOUT}
+ """
+
+ When I run `wp --require=table_names.php get_table_names --url=example.com/foo --scope=blog`
+ Then STDOUT should contain:
+ """
+ wp_2_commentmeta
+ wp_2_comments
+ wp_2_links
+ wp_2_options
+ wp_2_postmeta
+ wp_2_posts
+ wp_2_term_relationships
+ wp_2_term_taxonomy
+ """
+ # Leave out wp_2_termmeta for old WP compat.
+ And STDOUT should contain:
+ """
+ wp_2_terms
+ """
+ And save STDOUT as {SUBSITE_BLOG_STDOUT}
+
+ When I run `wp --require=table_names.php get_table_names --url=example.com/foo`
+ Then STDOUT should be:
+ """
+ {SUBSITE_BLOG_STDOUT}
+ {GLOBAL_STDOUT}
+ """
+
+ When I run `wp --require=table_names.php get_table_names --network`
+ Then STDOUT should be:
+ """
+ {SUBSITE_BLOG_STDOUT}
+ {DEFAULT_STDOUT}
+ """
+ And save STDOUT as {NETWORK_STDOUT}
+
+ When I run `wp --require=table_names.php get_table_names --network --url=example.com/foo`
+ Then STDOUT should be:
+ """
+ {NETWORK_STDOUT}
+ """
+
+ When I run `wp --require=table_names.php get_table_names --all-tables-with-prefix`
+ Then STDOUT should contain:
+ """
+ wp_2_commentmeta
+ wp_2_comments
+ wp_2_links
+ wp_2_options
+ wp_2_postmeta
+ wp_2_posts
+ wp_2_posts_xx
+ wp_2_term_relationships
+ wp_2_term_taxonomy
+ """
+ # Leave out wp_2_termmeta for old WP compat.
+ And STDOUT should contain:
+ """
+ wp_2_terms
+ wp_2_xx_posts
+ wp_blog_versions
+ wp_blogs
+ wp_categories
+ wp_commentmeta
+ wp_comments
+ wp_links
+ wp_options
+ wp_postmeta
+ wp_posts
+ wp_posts_xx
+ wp_registration_log
+ wp_signups
+ wp_site
+ wp_sitecategories
+ wp_sitemeta
+ wp_term_relationships
+ wp_term_taxonomy
+ """
+ # Leave out wp_termmeta for old WP compat.
+ And STDOUT should contain:
+ """
+ wp_terms
+ wp_usermeta
+ wp_users
+ wp_xx_posts
+ """
+ And save STDOUT as {ALL_TABLES_WITH_PREFIX_STDOUT}
+
+ # Network overriden by all-tables-with-prefix.
+ When I run `wp --require=table_names.php get_table_names --all-tables-with-prefix --network`
+ Then STDOUT should contain:
+ """
+ {ALL_TABLES_WITH_PREFIX_STDOUT}
+ """
+
+ When I run `wp --require=table_names.php get_table_names --all-tables`
+ Then STDOUT should be:
+ """
+ {ALL_TABLES_WITH_PREFIX_STDOUT}
+ xx_wp_2_posts
+ xx_wp_posts
+ """
+ And save STDOUT as {ALL_TABLES_STDOUT}
+
+ # Network overriden by all-tables.
+ When I run `wp --require=table_names.php get_table_names --all-tables --network`
+ Then STDOUT should be:
+ """
+ {ALL_TABLES_STDOUT}
+ """
+
+ When I run `wp --require=table_names.php get_table_names '*_posts'`
+ Then STDOUT should be:
+ """
+ wp_posts
+ """
+
+ When I run `wp --require=table_names.php get_table_names '*_posts' --network`
+ Then STDOUT should be:
+ """
+ wp_2_posts
+ wp_posts
+ """
+
+ When I run `wp --require=table_names.php get_table_names 'wp_post*'`
+ Then STDOUT should be:
+ """
+ wp_postmeta
+ wp_posts
+ """
+
+ When I run `wp --require=table_names.php get_table_names 'wp_post*' --network`
+ Then STDOUT should be:
+ """
+ wp_postmeta
+ wp_posts
+ """
+
+ When I run `wp --require=table_names.php get_table_names 'wp*osts'`
+ Then STDOUT should be:
+ """
+ wp_posts
+ """
+
+ When I run `wp --require=table_names.php get_table_names 'wp*osts' --network`
+ Then STDOUT should be:
+ """
+ wp_2_posts
+ wp_posts
+ """
+
+ When I run `wp --require=table_names.php get_table_names '*_posts' --scope=blog`
+ Then STDOUT should be:
+ """
+ wp_posts
+ """
+
+ When I run `wp --require=table_names.php get_table_names '*_posts' --scope=blog --network`
+ Then STDOUT should be:
+ """
+ wp_2_posts
+ wp_posts
+ """
+
+ When I try `wp --require=table_names.php get_table_names '*_posts' --scope=global`
+ Then STDERR should be:
+ """
+ Error: Couldn't find any tables matching: *_posts
+ """
+ And STDOUT should be empty
+
+ # Note: BC change 1.5.0, network does not override scope.
+ When I try `wp --require=table_names.php get_table_names '*_posts' --scope=global --network`
+ Then STDERR should be:
+ """
+ Error: Couldn't find any tables matching: *_posts
+ """
+ And STDOUT should be empty
+
+ When I run `wp --require=table_names.php get_table_names '*_posts' --all-tables-with-prefix`
+ Then STDOUT should be:
+ """
+ wp_2_posts
+ wp_2_xx_posts
+ wp_posts
+ wp_xx_posts
+ """
+
+ When I run `wp --require=table_names.php get_table_names 'wp_post*' --all-tables-with-prefix`
+ Then STDOUT should be:
+ """
+ wp_postmeta
+ wp_posts
+ wp_posts_xx
+ """
+
+ When I run `wp --require=table_names.php get_table_names 'wp*osts' --all-tables-with-prefix`
+ Then STDOUT should be:
+ """
+ wp_2_posts
+ wp_2_xx_posts
+ wp_posts
+ wp_xx_posts
+ """
+
+ When I run `wp --require=table_names.php get_table_names '*_posts' --all-tables`
+ Then STDOUT should be:
+ """
+ wp_2_posts
+ wp_2_xx_posts
+ wp_posts
+ wp_xx_posts
+ xx_wp_2_posts
+ xx_wp_posts
+ """
+
+ When I run `wp --require=table_names.php get_table_names '*wp_posts' --all-tables`
+ Then STDOUT should be:
+ """
+ wp_posts
+ xx_wp_posts
+ """
+
+ When I run `wp --require=table_names.php get_table_names 'wp_post*' --all-tables`
+ Then STDOUT should be:
+ """
+ wp_postmeta
+ wp_posts
+ wp_posts_xx
+ """
+
+ When I run `wp --require=table_names.php get_table_names 'wp*osts' --all-tables`
+ Then STDOUT should be:
+ """
+ wp_2_posts
+ wp_2_xx_posts
+ wp_posts
+ wp_xx_posts
+ """
+
+ When I try `wp --require=table_names.php get_table_names non_existent_table`
+ Then STDERR should be:
+ """
+ Error: Couldn't find any tables matching: non_existent_table
+ """
+ And STDOUT should be empty
+
+ When I run `wp --require=table_names.php get_table_names wp_posts non_existent_table`
+ Then STDOUT should be:
+ """
+ wp_posts
+ """
+
+ When I run `wp --require=table_names.php get_table_names wp_posts non_existent_table 'wp_?ption*'`
+ Then STDOUT should be:
+ """
+ wp_options
+ wp_posts
+ """
+
+ When I run `wp --require=table_names.php get_table_names wp_posts non_existent_table 'wp_*ption?'`
+ Then STDOUT should be:
+ """
+ wp_options
+ wp_posts
+ """
+
+ When I run `wp --require=table_names.php get_table_names wp_posts non_existent_table 'wp_*ption?' --network`
+ Then STDOUT should be:
+ """
+ wp_2_options
+ wp_options
+ wp_posts
+ """
+
+ Given an enable_sitecategories.php file:
+ """
+ } --skip-wordpress eval 'WP_CLI\Utils\run_mysql_command( null, array() );'`
+ Then STDERR should contain:
+ """
+ Error: Cannot do 'run_mysql_command': The PHP functions `proc_open()` and/or `proc_close()` are disabled
+ """
+ And STDOUT should be empty
+ And the return code should be 1
+
+ Examples:
+ | func |
+ | proc_open |
+ | proc_close |
+
+ Scenario Outline: Check that `proc_open()` and `proc_close()` aren't disabled for `Utils\launch_editor_for_input()`
+ When I try `{INVOKE_WP_CLI_WITH_PHP_ARGS--ddisable_functions=} --skip-wordpress eval 'WP_CLI\Utils\launch_editor_for_input( null, null );'`
+ Then STDERR should contain:
+ """
+ Error: Cannot do 'launch_editor_for_input': The PHP functions `proc_open()` and/or `proc_close()` are disabled
+ """
+ And STDOUT should be empty
+ And the return code should be 1
+
+ Examples:
+ | func |
+ | proc_open |
+ | proc_close |
+
+ # INI directive `sys_temp_dir` introduced PHP 5.5.0.
+ @require-php-5.5
+ Scenario: Check `Utils\get_temp_dir()` when `sys_temp_dir` directive set
+ # `sys_temp_dir` set to unwritable.
+ When I try `{INVOKE_WP_CLI_WITH_PHP_ARGS--dsys_temp_dir=\\no_such_directory/} --skip-wordpress eval 'echo WP_CLI\Utils\get_temp_dir();'`
+ Then STDERR should contain:
+ """
+ Warning: Temp directory isn't writable
+ """
+ And STDERR should contain:
+ """
+ /no_such_directory/
+ """
+ And STDOUT should be:
+ """
+ /no_such_directory/
+ """
+ And the return code should be 0
+
+ # `sys_temp_dir` unset.
+ When I run `{INVOKE_WP_CLI_WITH_PHP_ARGS--dsys_temp_dir=} --skip-wordpress eval 'echo WP_CLI\Utils\get_temp_dir();'`
+ Then STDOUT should match /\/$/
diff --git a/features/validation.feature b/features/validation.feature
index 15e9c040db..bcd8c8efac 100644
--- a/features/validation.feature
+++ b/features/validation.feature
@@ -17,9 +17,8 @@ Feature: Argument validation
Given an empty directory
And WP files
- When I try `wp core config`
- Then the return code should be 1
- And STDERR should contain:
+ When I mistakenly try `wp core config`
+ Then STDERR should contain:
"""
Parameter errors:
"""
@@ -28,9 +27,8 @@ Feature: Argument validation
missing --dbname parameter
"""
- When I try `wp core config --invalid --other-invalid`
- Then the return code should be 1
- And STDERR should contain:
+ When I mistakenly try `wp core config --invalid --other-invalid`
+ Then STDERR should contain:
"""
unknown --invalid parameter
"""
@@ -39,10 +37,8 @@ Feature: Argument validation
unknown --other-invalid parameter
"""
- When I try `wp core version invalid`
- Then the return code should be 1
- And STDERR should contain:
+ When I mistakenly try `wp core version invalid`
+ Then STDERR should contain:
"""
Error: Too many positional arguments: invalid
"""
- And STDOUT should be empty
diff --git a/php/WP_CLI/Bootstrap/AutoloaderStep.php b/php/WP_CLI/Bootstrap/AutoloaderStep.php
index 4818771edf..b7cf3ce015 100644
--- a/php/WP_CLI/Bootstrap/AutoloaderStep.php
+++ b/php/WP_CLI/Bootstrap/AutoloaderStep.php
@@ -63,20 +63,26 @@ public function process( BootstrapState $state ) {
* @return string|false Name of the custom vendor folder or false if none.
*/
protected function get_custom_vendor_folder() {
- $maybe_composer_json = WP_CLI_ROOT . '/../../../composer.json';
- if ( ! is_readable( $maybe_composer_json ) ) {
- return false;
- }
+ static $result = null;
+
+ if ( null === $result ) {
+ $maybe_composer_json = WP_CLI_ROOT . '/../../../composer.json';
+ if ( ! is_readable( $maybe_composer_json ) ) {
+ return $result = false;
+ }
- $composer = json_decode( file_get_contents( $maybe_composer_json ) );
+ $composer = json_decode( file_get_contents( $maybe_composer_json ) );
+
+ if ( ! empty( $composer->config )
+ && ! empty( $composer->config->{'vendor-dir'} )
+ ) {
+ return $result = $composer->config->{'vendor-dir'};
+ }
- if ( ! empty( $composer->config )
- && ! empty( $composer->config->{'vendor-dir'} )
- ) {
- return $composer->config->{'vendor-dir'};
+ return $result = false;
}
- return false;
+ return $result;
}
/**
diff --git a/php/WP_CLI/Bootstrap/RunnerInstance.php b/php/WP_CLI/Bootstrap/RunnerInstance.php
index dceddb99b1..e2736ddc06 100644
--- a/php/WP_CLI/Bootstrap/RunnerInstance.php
+++ b/php/WP_CLI/Bootstrap/RunnerInstance.php
@@ -20,11 +20,11 @@ final class RunnerInstance {
*/
public function __invoke() {
if ( ! class_exists( 'WP_CLI\Runner' ) ) {
- require_once WP_CLI_ROOT . '/php/WP_CLI/Runner.php';
+ require WP_CLI_ROOT . '/php/WP_CLI/Runner.php';
}
if ( ! class_exists( 'WP_CLI\Configurator' ) ) {
- require_once WP_CLI_ROOT . '/php/WP_CLI/Configurator.php';
+ require WP_CLI_ROOT . '/php/WP_CLI/Configurator.php';
}
return \WP_CLI::get_runner();
diff --git a/php/WP_CLI/Completions.php b/php/WP_CLI/Completions.php
index 9de6ee6e4d..957fd30cc2 100644
--- a/php/WP_CLI/Completions.php
+++ b/php/WP_CLI/Completions.php
@@ -6,6 +6,7 @@ class Completions {
private $words;
private $opts = array();
+ private $cur_word;
public function __construct( $line ) {
// TODO: properly parse single and double quotes
diff --git a/php/WP_CLI/Configurator.php b/php/WP_CLI/Configurator.php
index d099eddec8..27f46640f5 100644
--- a/php/WP_CLI/Configurator.php
+++ b/php/WP_CLI/Configurator.php
@@ -3,6 +3,7 @@
namespace WP_CLI;
use Mustangostang\Spyc;
+use WP_CLI\Utils;
/**
* Handles file- and runtime-based configuration values.
@@ -323,10 +324,15 @@ private static function load_yml( $yml_file ) {
$config['config create'] = $config['core config'];
unset( $config['core config'] );
}
- // 'core verify-checksums' -> 'checksum core'
- if ( isset( $config['core verify-checksums'] ) ) {
- $config['checksum core'] = $config['core verify-checksums'];
- unset( $config['core verify-checksums'] );
+ // 'checksum core' -> 'core verify-checksums'
+ if ( isset( $config['checksum core'] ) ) {
+ $config['core verify-checksums'] = $config['checksum core'];
+ unset( $config['checksum core'] );
+ }
+ // 'checksum plugin' -> 'plugin verify-checksums'
+ if ( isset( $config['checksum plugin'] ) ) {
+ $config['plugin verify-checksums'] = $config['checksum plugin'];
+ unset( $config['checksum plugin'] );
}
return $config;
@@ -349,8 +355,9 @@ private static function arrayify( &$val ) {
*/
private static function absolutize( &$path, $base ) {
if ( ! empty( $path ) && ! \WP_CLI\Utils\is_path_absolute( $path ) ) {
- $path = $base . DIRECTORY_SEPARATOR . $path;
+ $path = $base . '/' . $path;
}
+ $path = Utils\normalize_directory_separators( $path );
}
}
diff --git a/php/WP_CLI/Dispatcher/CommandFactory.php b/php/WP_CLI/Dispatcher/CommandFactory.php
index 50af3ee28d..b1b4cbc7b2 100644
--- a/php/WP_CLI/Dispatcher/CommandFactory.php
+++ b/php/WP_CLI/Dispatcher/CommandFactory.php
@@ -16,7 +16,7 @@ class CommandFactory {
* Create a new CompositeCommand (or Subcommand if class has __invoke())
*
* @param string $name Represents how the command should be invoked
- * @param string $callable A subclass of WP_CLI_Command, a function, or a closure
+ * @param object|string|array $callable A subclass of WP_CLI_Command, a function, or a closure
* @param mixed $parent The new command's parent Composite (or Root) command
*/
public static function create( $name, $callable, $parent ) {
@@ -60,11 +60,9 @@ public static function clear_file_contents_cache() {
* Create a new Subcommand instance.
*
* @param mixed $parent The new command's parent Composite command
- * @param string $name Represents how the command should be invoked
+ * @param string|bool $name Represents how the command should be invoked. If false it's set from the docblock or reflection name.
* @param mixed $callable A callable function or closure, or class name and method
* @param object $reflection Reflection instance, for doc parsing
- * @param string $class A subclass of WP_CLI_Command
- * @param string $method Class method to be called upon invocation.
*/
private static function create_subcommand( $parent, $name, $callable, $reflection ) {
$doc_comment = self::get_doc_comment( $reflection );
@@ -149,7 +147,7 @@ private static function create_namespace( $parent, $name, $callable ) {
/**
* Check whether a method is actually callable.
*
- * @param ReflectionMethod $method
+ * @param \ReflectionMethod $method
* @return bool
*/
private static function is_good_method( $method ) {
@@ -159,7 +157,7 @@ private static function is_good_method( $method ) {
/**
* Gets the document comment. Caters for PHP directive `opcache.save comments` being disabled.
*
- * @param ReflectionMethod|ReflectionClass|ReflectionFunction $reflection Reflection instance.
+ * @param \ReflectionMethod|\ReflectionClass|\ReflectionFunction $reflection Reflection instance.
* @return string|false|null Doc comment string if any, false if none (same as `Reflection*::getDocComment()`), null if error.
*/
private static function get_doc_comment( $reflection ) {
diff --git a/php/WP_CLI/Dispatcher/CompositeCommand.php b/php/WP_CLI/Dispatcher/CompositeCommand.php
index a00358f78b..55b52f0e35 100644
--- a/php/WP_CLI/Dispatcher/CompositeCommand.php
+++ b/php/WP_CLI/Dispatcher/CompositeCommand.php
@@ -12,7 +12,8 @@
*/
class CompositeCommand {
- protected $name, $shortdesc, $synopsis, $docparser;
+ protected $name, $shortdesc, $longdesc, $docparser;
+ protected $synopsis; // Used by Subcommand.
protected $parent, $subcommands = array();
@@ -117,7 +118,7 @@ public function get_shortdesc() {
* @param string
*/
public function set_shortdesc( $shortdesc ) {
- $this->shortdesc = $shortdesc;
+ $this->shortdesc = Utils\normalize_eols( $shortdesc );
}
/**
@@ -136,7 +137,7 @@ public function get_longdesc() {
* @param string
*/
public function set_longdesc( $longdesc ) {
- $this->longdesc = $longdesc;
+ $this->longdesc = Utils\normalize_eols( $longdesc );
}
/**
@@ -252,7 +253,7 @@ private static function get_aliases( $subcommands ) {
/**
* Composite commands can only be known by one name.
*
- * @return false
+ * @return false|string
*/
public function get_alias() {
return false;
diff --git a/php/WP_CLI/DocParser.php b/php/WP_CLI/DocParser.php
index 303f0b8e69..033d6f3847 100644
--- a/php/WP_CLI/DocParser.php
+++ b/php/WP_CLI/DocParser.php
@@ -64,15 +64,7 @@ public function get_longdesc() {
$longdesc = substr( $this->docComment, strlen( $shortdesc ) );
- $lines = array();
- foreach ( explode( "\n", $longdesc ) as $line ) {
- if ( 0 === strpos( $line, '@' ) ) {
- break;
- }
-
- $lines[] = $line;
- }
- $longdesc = trim( implode( $lines, "\n" ) );
+ $longdesc = trim( preg_replace( '/^@.*\z/ms', '', $longdesc ) );
return $longdesc;
}
diff --git a/php/WP_CLI/Extractor.php b/php/WP_CLI/Extractor.php
index 4e1e9a66e1..fbb65d83dc 100644
--- a/php/WP_CLI/Extractor.php
+++ b/php/WP_CLI/Extractor.php
@@ -38,29 +38,32 @@ public static function extract( $tarball_or_zip, $dest ) {
* @param string $dest
*/
private static function extract_zip( $zipfile, $dest ) {
+ if ( class_exists( 'PharData' ) && ! getenv( 'WP_CLI_TEST_EXTRACTOR_ZIP_ARCHIVE' ) ) {
+ try {
+ self::copy_overwrite_files( 'phar://' . $zipfile, $dest, 1 /*strip_components*/ );
+ return;
+ } catch ( \Exception $e ) {
+ WP_CLI::warning( sprintf( 'Falling back to ZipArchive. PharData failed: %s.', $e->getMessage() ) );
+ }
+ }
if ( ! class_exists( 'ZipArchive' ) ) {
- throw new \Exception( 'Extracting a zip file requires ZipArchive.' );
+ throw new \Exception( 'Extracting a zip file requires ZipArchive or PharData.' );
}
$zip = new ZipArchive();
$res = $zip->open( $zipfile );
- if ( true === $res ) {
- $tempdir = implode(
- DIRECTORY_SEPARATOR,
- array(
- dirname( $zipfile ),
- Utils\basename( $zipfile, '.zip' ),
- $zip->getNameIndex( 0 ),
- )
- );
-
- $zip->extractTo( dirname( $tempdir ) );
- $zip->close();
-
- self::copy_overwrite_files( $tempdir, $dest );
- self::rmdir( dirname( $tempdir ) );
- } else {
- throw new \Exception( sprintf( "ZipArchive failed to unzip '%s': %s.", $zipfile, self::zip_error_msg( $res ) ) );
+ if ( true !== $res ) {
+ throw new \Exception( sprintf( "ZipArchive failed to open '%s': %s.", $zipfile, self::zip_error_msg( $res ) ) );
+ }
+ $tempdir = Utils\get_temp_dir() . uniqid( 'wp-cli-extract-zip-', true );
+
+ if ( ! $zip->extractTo( $tempdir ) ) {
+ throw new \Exception( sprintf( "ZipArchive failed to extract '%s' to temporary directory '%s'.", $zipfile, $tempdir ) );
+ }
+ if ( ! $zip->close() ) {
+ throw new \Exception( sprintf( "ZipArchive failed to close '%s'.", $zipfile ) );
}
+ self::copy_overwrite_files( $tempdir, $dest, 1 /*strip_components*/ );
+ self::rmdir( $tempdir );
}
/**
@@ -71,31 +74,43 @@ private static function extract_zip( $zipfile, $dest ) {
*/
private static function extract_tarball( $tarball, $dest ) {
- if ( class_exists( 'PharData' ) ) {
+ if ( class_exists( 'PharData' ) && ! getenv( 'WP_CLI_TEST_EXTRACTOR_SHELL' ) ) {
try {
- $phar = new PharData( $tarball );
- $tempdir = implode(
- DIRECTORY_SEPARATOR,
- array(
- dirname( $tarball ),
- Utils\basename( $tarball, '.tar.gz' ),
- $phar->getFilename(),
- )
- );
-
- $phar->extractTo( dirname( $tempdir ), null, true );
-
- self::copy_overwrite_files( $tempdir, $dest );
+ // Check if PHP bug #75273 likely to be triggered and copy to temporary tar if so.
+ $pre_tar = false;
+ // Only checking Ubuntu (and derivatives) as unfortunately Debian doesn't sign its PHP build so not easy to check for it.
+ if ( false !== strpos( PHP_VERSION, 'ubuntu' ) ) {
+ $tar_size = filesize( $tarball );
+ $pre_tar = $tar_size > 4 * 1024 * 1024 && $tar_size % ( 8 * 1024 ) < 10;
+ }
+ if ( $pre_tar ) {
+ $temp_tar = Utils\get_temp_dir() . uniqid( 'wp-cli-extract-', true ) . '.tar';
+ if ( false === ( $contents = file_get_contents( 'compress.zlib://' . $tarball ) ) || false === file_put_contents( $temp_tar, $contents ) ) {
+ throw new \Exception( sprintf( "Failed to create temporary tar '%s'.", $temp_tar ) );
+ }
+
+ self::copy_overwrite_files( 'phar://' . $temp_tar, $dest, 1 /*strip_components*/ );
+ unlink( $temp_tar );
+ } else {
- self::rmdir( dirname( $tempdir ) );
+ self::copy_overwrite_files( 'phar://' . $tarball, $dest, 1 /*strip_components*/ );
+ }
return;
} catch ( \Exception $e ) {
- WP_CLI::warning( "PharData failed, falling back to 'tar xz' (" . $e->getMessage() . ')' );
+ // Can fail on Debian due to PHP bug #75273 so don't warn but fall through silently if message matches.
+ if ( $pre_tar || sprintf( 'unable to decompress gzipped phar archive "%s" to temporary file', $tarball ) !== $e->getMessage() ) {
+ WP_CLI::warning( sprintf( "Falling back to 'tar xz'. PharData failed: %s.", $e->getMessage() ) );
+ }
// Fall through to trying `tar xz` below
}
}
- // Note: directory must exist for tar --directory to work.
- $cmd = Utils\esc_cmd( 'tar xz --strip-components=1 --directory=%s -f %s', $dest, $tarball );
+
+ // Directory must exist for tar --directory to work.
+ if ( ! file_exists( $dest ) ) {
+ mkdir( $dest, 0777, true );
+ }
+ // Need --force-local for Windows to avoid "C:" being interpreted as referring to remote machine.
+ $cmd = Utils\esc_cmd( 'tar xz --force-local --strip-components=1 --directory=%2$s -f %1$s', $tarball, $dest );
$process_run = WP_CLI::launch( $cmd, false /*exit_on_error*/, true /*return_detailed*/ );
if ( 0 !== $process_run->return_code ) {
throw new \Exception( sprintf( 'Failed to execute `%s`: %s.', $cmd, self::tar_error_msg( $process_run ) ) );
@@ -108,41 +123,38 @@ private static function extract_tarball( $tarball, $dest ) {
* @param string $source
* @param string $dest
*/
- public static function copy_overwrite_files( $source, $dest ) {
- $iterator = new RecursiveIteratorIterator(
- new RecursiveDirectoryIterator( $source, RecursiveDirectoryIterator::SKIP_DOTS ),
- RecursiveIteratorIterator::SELF_FIRST
- );
-
- $error = 0;
+ public static function copy_overwrite_files( $source, $dest, $strip_components = 0 ) {
+ if ( false === ( $files = scandir( $source ) ) ) {
+ $error = error_get_last();
+ throw new \Exception( sprintf( "Failed to scan source directory '%s': %s", $source, $error['message'] ) );
+ }
- if ( ! is_dir( $dest ) ) {
- mkdir( $dest, 0777, true );
+ if ( ! file_exists( $dest ) && ! mkdir( $dest, 0777, true ) ) {
+ $error = error_get_last();
+ throw new \Exception( sprintf( "Failed to create destination directory '%s': %s", $dest, $error['message'] ) );
}
- foreach ( $iterator as $item ) {
+ foreach ( array_diff( $files, array( '.', '..' ) ) as $file ) {
- $dest_path = $dest . DIRECTORY_SEPARATOR . $iterator->getSubPathName();
+ $source_file = $source . '/' . $file;
+ $dest_file = $dest . '/' . $file;
- if ( $item->isDir() ) {
- if ( ! is_dir( $dest_path ) ) {
- mkdir( $dest_path );
+ if ( $strip_components > 0 ) {
+ if ( is_dir( $source_file ) ) {
+ self::copy_overwrite_files( $source_file, $dest, $strip_components - 1 );
}
} else {
- if ( file_exists( $dest_path ) && is_writable( $dest_path ) ) {
- copy( $item, $dest_path );
- } elseif ( ! file_exists( $dest_path ) ) {
- copy( $item, $dest_path );
+
+ if ( is_dir( $source_file ) ) {
+ self::copy_overwrite_files( $source_file, $dest_file );
} else {
- $error = 1;
- WP_CLI::warning( "Unable to copy '" . $iterator->getSubPathName() . "' to current directory." );
+ if ( ! copy( $source_file, $dest_file ) ) {
+ $error = error_get_last();
+ throw new \Exception( sprintf( "Failed to copy '%s' to target '%s': %s.", $source_file, $dest_file, $error['message'] ) );
+ }
}
}
}
-
- if ( $error ) {
- throw new \Exception( 'There was an error overwriting existing files.' );
- }
}
/**
diff --git a/php/WP_CLI/FileCache.php b/php/WP_CLI/FileCache.php
index ff7da52149..ab0ff8acc0 100644
--- a/php/WP_CLI/FileCache.php
+++ b/php/WP_CLI/FileCache.php
@@ -40,6 +40,10 @@ class FileCache {
* @var string key allowed chars (regex class)
*/
protected $whitelist;
+ /**
+ * @var bool finderDummy dummy to autoload Finder classes.
+ */
+ static private $finderDummy = null;
/**
* @param string $cacheDir location of the cache
@@ -57,6 +61,13 @@ public function __construct( $cacheDir, $ttl, $maxSize, $whitelist = 'a-z0-9._-'
$this->enabled = false;
}
+ if ( null === self::$finderDummy && $this->enabled ) {
+ /*
+ * Make sure Finder & helper classes used in clean() are loaded as otherwise calling clean() in a `register_shutdown_function`
+ * can fail in certain circumstances - a PHP issue not easily reproducible but witnessed on Travis and locally.
+ */
+ self::$finderDummy = (bool) $this->get_finder()->files()->name( basename( __FILE__ ) )->in( __DIR__ )->date( '> 1999' )->sortByAccessedTime()->getIterator()->current()->getSize();
+ }
}
/**
diff --git a/php/WP_CLI/Process.php b/php/WP_CLI/Process.php
index 584f679b9c..315aa869ad 100644
--- a/php/WP_CLI/Process.php
+++ b/php/WP_CLI/Process.php
@@ -49,7 +49,7 @@ class Process {
*
* @return Process
*/
- public static function create( $command, $cwd = null, $env = array() ) {
+ public static function create( $command, $cwd = null, $env = null ) {
$proc = new self;
$proc->command = $command;
@@ -133,4 +133,25 @@ public function run_check_stderr() {
return $r;
}
+
+ /**
+ * Run the command, but throw an Exception if the non-null args aren't as given.
+ *
+ * @return ProcessRun
+ */
+ public function run_check_args( $return_code = null, $stderr_empty = null, $stdout_empty = null ) {
+ $r = $this->run();
+
+ if ( null !== $return_code && $r->return_code !== $return_code ) {
+ throw new \RuntimeException( $r );
+ }
+ if ( null !== $stderr_empty && empty( $r->stderr ) !== $stderr_empty ) {
+ throw new \RuntimeException( $r );
+ }
+ if ( null !== $stdout_empty && empty( $r->stdout ) !== $stdout_empty ) {
+ throw new \RuntimeException( $r );
+ }
+
+ return $r;
+ }
}
diff --git a/php/WP_CLI/Runner.php b/php/WP_CLI/Runner.php
index 50a6eae5cb..aff0881042 100644
--- a/php/WP_CLI/Runner.php
+++ b/php/WP_CLI/Runner.php
@@ -616,9 +616,14 @@ private static function back_compat_conversions( $args, $assoc_args ) {
list( $args[0], $args[1] ) = array( 'language', 'core' );
}
- // core verify-checksums -> checksum core
- if ( array( 'core', 'verify-checksums' ) == array_slice( $args, 0, 2 ) ) {
- list( $args[0], $args[1] ) = array( 'checksum', 'core' );
+ // checksum core -> core verify-checksums
+ if ( array( 'checksum', 'core' ) == array_slice( $args, 0, 2 ) ) {
+ list( $args[0], $args[1] ) = array( 'core', 'verify-checksums' );
+ }
+
+ // checksum plugin -> plugin verify-checksums
+ if ( array( 'checksum', 'plugin' ) == array_slice( $args, 0, 2 ) ) {
+ list( $args[0], $args[1] ) = array( 'plugin', 'verify-checksums' );
}
// site create --site_id= -> site create --network_id=
@@ -723,6 +728,29 @@ private static function back_compat_conversions( $args, $assoc_args ) {
}
}
+ // config get --[global|constant]= --> config get --type=constant|variable
+ // config get --> config list
+ if ( count( $args ) === 2
+ && 'config' === $args[0]
+ && 'get' === $args[1] ) {
+ if ( isset( $assoc_args['global'] ) ) {
+ $name = $assoc_args['global'];
+ $type = 'variable';
+ unset( $assoc_args['global'] );
+ } elseif ( isset( $assoc_args['constant'] ) ) {
+ $name = $assoc_args['constant'];
+ $type = 'constant';
+ unset( $assoc_args['constant'] );
+ }
+ if ( ! empty( $name ) && ! empty( $type ) ) {
+ $args[] = $name;
+ $assoc_args['type'] = $type;
+ } else {
+ // We had a 'config get' without a '', so assume 'list' was wanted.
+ $args[1] = 'list';
+ }
+ }
+
return array( $args, $assoc_args );
}
@@ -763,11 +791,22 @@ public function get_required_files() {
* @return bool
*/
private function wp_exists() {
+ return file_exists( ABSPATH . 'wp-includes/version.php' );
+ }
+
+ /**
+ * Are WordPress core files readable?
+ *
+ * @return bool
+ */
+ private function wp_is_readable() {
return is_readable( ABSPATH . 'wp-includes/version.php' );
}
private function check_wp_version() {
- if ( ! $this->wp_exists() ) {
+ $wp_exists = $this->wp_exists();
+ $wp_is_readable = $this->wp_is_readable();
+ if ( ! $wp_exists || ! $wp_is_readable ) {
$this->show_synopsis_if_composite_command();
// If the command doesn't exist use as error.
$args = $this->cmd_starts_with( array( 'help' ) ) ? array_slice( $this->arguments, 1 ) : $this->arguments;
@@ -778,6 +817,12 @@ private function check_wp_version() {
}
WP_CLI::error( $suggestion_or_disabled );
}
+
+ if ( $wp_exists && ! $wp_is_readable ) {
+ WP_CLI::error(
+ 'It seems, the WordPress core files do not have the proper file permissions.'
+ );
+ }
WP_CLI::error(
"This does not seem to be a WordPress install.\n" .
'Pass --path=`path/to/wordpress` or run `wp core download`.'
@@ -1578,7 +1623,7 @@ private function auto_check_update() {
}
// Only check for update when a human is operating.
- if ( ! function_exists( 'posix_isatty' ) || ! posix_isatty( STDOUT ) ) {
+ if ( Utils\isPiped() ) {
return;
}
@@ -1610,6 +1655,18 @@ private function auto_check_update() {
// In case the operation fails, ensure the timestamp has been updated.
$cache->write( $cache_key, time() );
+ // Ask before doing remote request.
+ $current_command = implode( ' ', $this->arguments );
+ $msg = sprintf(
+ "(Note you can control whether and when to auto-check for updates with the 'WP_CLI_DISABLE_AUTO_CHECK_UPDATE' and 'WP_CLI_AUTO_CHECK_UPDATE_DAYS' environment variables.)\n" .
+ 'You have version %s. Would you like to check if an update of WP-CLI is available?', WP_CLI_VERSION
+ );
+ if ( ! WP_CLI::ask( $msg ) ) {
+ WP_CLI::log( sprintf( "Continuing with your current command '%s'...", $current_command ) );
+ return;
+ }
+
+ WP_CLI::log( 'Checking for an update of WP-CLI...' );
// Check whether any updates are available.
ob_start();
WP_CLI::run_command(
@@ -1624,9 +1681,12 @@ private function auto_check_update() {
}
// Looks like an update is available, so let's prompt to update.
+ WP_CLI::log( sprintf( "Update found - invoking 'cli update' (please note that if you decide to update, your current command '%s' will not complete)...", $current_command ) );
+
WP_CLI::run_command( array( 'cli', 'update' ) );
- // If the Phar was replaced, we can't proceed with the original process.
- exit;
+
+ // If the Phar was replaced, we've exited so don't get here.
+ WP_CLI::log( sprintf( "Continuing with your current command '%s'...", $current_command ) );
}
/**
diff --git a/php/class-wp-cli.php b/php/class-wp-cli.php
index 18cefd9beb..5e3817c55f 100644
--- a/php/class-wp-cli.php
+++ b/php/class-wp-cli.php
@@ -510,9 +510,9 @@ public static function add_command( $name, $callable, $args = array() ) {
$long_desc = '';
$bits = explode( ' ', $synopsis );
foreach ( $args['synopsis'] as $key => $arg ) {
- $long_desc .= $bits[ $key ] . PHP_EOL;
+ $long_desc .= $bits[ $key ] . "\n";
if ( ! empty( $arg['description'] ) ) {
- $long_desc .= ': ' . $arg['description'] . PHP_EOL;
+ $long_desc .= ': ' . $arg['description'] . "\n";
}
$yamlify = array();
foreach ( array( 'default', 'options' ) as $key ) {
@@ -522,13 +522,16 @@ public static function add_command( $name, $callable, $args = array() ) {
}
if ( ! empty( $yamlify ) ) {
$long_desc .= Spyc::YAMLDump( $yamlify );
- $long_desc .= '---' . PHP_EOL;
+ $long_desc .= '---' . "\n";
}
- $long_desc .= PHP_EOL;
+ $long_desc .= "\n";
}
if ( ! empty( $long_desc ) ) {
- $long_desc = rtrim( $long_desc, PHP_EOL );
- $long_desc = '## OPTIONS' . PHP_EOL . PHP_EOL . $long_desc;
+ $long_desc = rtrim( $long_desc, "\r\n" );
+ $long_desc = '## OPTIONS' . "\n\n" . $long_desc;
+ if ( ! empty( $args['longdesc'] ) ) {
+ $long_desc .= "\n\n" . ltrim( $args['longdesc'], "\r\n" );
+ }
$leaf_command->set_longdesc( $long_desc );
}
}
@@ -816,15 +819,32 @@ public static function error_multi_line( $message_lines ) {
* @param array $assoc_args Skips prompt if 'yes' is provided.
*/
public static function confirm( $question, $assoc_args = array() ) {
+ if ( ! self::ask( $question, $assoc_args ) ) {
+ exit;
+ }
+ }
+
+ /**
+ * Ask for confirmation before doing something.
+ *
+ * If 'y' is provided to the question, it returns true. If
+ * 'n' or any other response is provided to the question, it returns false.
+ *
+ * @access public
+ * @category Input
+ *
+ * @param string $question Question to display before the prompt.
+ * @param array $assoc_args Skips prompt if 'yes' is provided.
+ */
+ public static function ask( $question, $assoc_args = array() ) {
if ( ! \WP_CLI\Utils\get_flag_value( $assoc_args, 'yes' ) ) {
fwrite( STDOUT, $question . ' [y/n] ' );
$answer = strtolower( trim( fgets( STDIN ) ) );
- if ( 'y' != $answer ) {
- exit;
- }
+ return 'y' === $answer;
}
+ return true;
}
/**
diff --git a/php/commands/help.php b/php/commands/help.php
index 91b810b347..d9b830c104 100644
--- a/php/commands/help.php
+++ b/php/commands/help.php
@@ -44,13 +44,16 @@ private static function show_help( $command ) {
$out = substr_replace( $out, $subcommands_header, $matches[1][1], strlen( $subcommands ) );
}
- $out .= self::parse_reference_links( $command->get_longdesc() );
+ if ( $longdesc = self::parse_reference_links( $command->get_longdesc() ) ) {
+ // Normalize newlines between parts.
+ $out = rtrim( $out, "\n" ) . "\n\n" . ltrim( $longdesc, "\n" );
+ }
// definition lists
$out = preg_replace_callback( '/([^\n]+)\n: (.+?)(\n\n|$)/s', array( __CLASS__, 'rewrap_param_desc' ), $out );
- // Ensure all non-section headers are indented.
- $out = preg_replace( '#^([^\s^\#])#m', "\t$1", $out );
+ // Ensure lines with no leading whitespace that aren't section headers are indented.
+ $out = preg_replace( '/^((?! |\t|##).)/m', "\t$1", $out );
$tab = str_repeat( ' ', 2 );
diff --git a/php/commands/src/CLI_Command.php b/php/commands/src/CLI_Command.php
index fa2474fd78..6465e6e613 100644
--- a/php/commands/src/CLI_Command.php
+++ b/php/commands/src/CLI_Command.php
@@ -130,18 +130,29 @@ public function info( $_, $assoc_args ) {
WP_CLI::line( json_encode( $info ) );
} else {
- WP_CLI::line( "OS:\t" . $system_os );
- WP_CLI::line( "Shell:\t" . $shell );
- WP_CLI::line( "PHP binary:\t" . $php_bin );
- WP_CLI::line( "PHP version:\t" . PHP_VERSION );
- WP_CLI::line( "php.ini used:\t" . get_cfg_var( 'cfg_file_path' ) );
- WP_CLI::line( "WP-CLI root dir:\t" . WP_CLI_ROOT );
- WP_CLI::line( "WP-CLI vendor dir:\t" . WP_CLI_VENDOR_DIR );
- WP_CLI::line( "WP_CLI phar path:\t" . ( defined( 'WP_CLI_PHAR_PATH' ) ? WP_CLI_PHAR_PATH : '' ) );
- WP_CLI::line( "WP-CLI packages dir:\t" . $packages_dir );
- WP_CLI::line( "WP-CLI global config:\t" . $runner->global_config_path );
- WP_CLI::line( "WP-CLI project config:\t" . $runner->project_config_path );
- WP_CLI::line( "WP-CLI version:\t" . WP_CLI_VERSION );
+
+ $info = array(
+ array( 'OS', $system_os ),
+ array( 'Shell', $shell ),
+ array( 'PHP binary', $php_bin ),
+ array( 'PHP version', PHP_VERSION ),
+ array( 'php.ini used', get_cfg_var( 'cfg_file_path' ) ),
+ array( 'WP-CLI root dir', WP_CLI_ROOT ),
+ array( 'WP-CLI vendor dir', WP_CLI_VENDOR_DIR ),
+ array( 'WP_CLI phar path', ( defined( 'WP_CLI_PHAR_PATH' ) ? WP_CLI_PHAR_PATH : '' ) ),
+ array( 'WP-CLI packages dir', $packages_dir ),
+ array( 'WP-CLI global config', $runner->global_config_path ),
+ array( 'WP-CLI project config', $runner->project_config_path ),
+ array( 'WP-CLI version', WP_CLI_VERSION ),
+ );
+
+ $info_table = new \cli\Table();
+ $info_table->setRows( $info );
+ $info_table->setRenderer( new \cli\table\Ascii() );
+ $lines = array_slice( $info_table->getDisplayLines(), 2 );
+ foreach ( $lines as $line ) {
+ \WP_CLI::line( $line );
+ }
}
}
@@ -269,11 +280,15 @@ public function update( $_, $assoc_args ) {
}
if ( Utils\get_flag_value( $assoc_args, 'nightly' ) ) {
- WP_CLI::confirm( sprintf( 'You have version %s. Would you like to update to the latest nightly?', WP_CLI_VERSION ), $assoc_args );
+ if ( ! WP_CLI::ask( sprintf( 'You have version %s. Would you like to update to the latest nightly?', WP_CLI_VERSION ), $assoc_args ) ) {
+ return;
+ }
$download_url = 'https://raw.githubusercontent.com/wp-cli/builds/gh-pages/phar/wp-cli-nightly.phar';
$md5_url = 'https://raw.githubusercontent.com/wp-cli/builds/gh-pages/phar/wp-cli-nightly.phar.md5';
} elseif ( Utils\get_flag_value( $assoc_args, 'stable' ) ) {
- WP_CLI::confirm( sprintf( 'You have version %s. Would you like to update to the latest stable release?', WP_CLI_VERSION ), $assoc_args );
+ if ( ! WP_CLI::ask( sprintf( 'You have version %s. Would you like to update to the latest stable release?', WP_CLI_VERSION ), $assoc_args ) ) {
+ return;
+ }
$download_url = 'https://raw.githubusercontent.com/wp-cli/builds/gh-pages/phar/wp-cli.phar';
$md5_url = 'https://raw.githubusercontent.com/wp-cli/builds/gh-pages/phar/wp-cli.phar.md5';
} else {
@@ -288,7 +303,9 @@ public function update( $_, $assoc_args ) {
$newest = $updates[0];
- WP_CLI::confirm( sprintf( 'You have version %s. Would you like to update to %s?', WP_CLI_VERSION, $newest['version'] ), $assoc_args );
+ if ( ! WP_CLI::ask( sprintf( 'You have version %s. Would you like to update to %s?', WP_CLI_VERSION, $newest['version'] ), $assoc_args ) ) {
+ return;
+ }
$download_url = $newest['package_url'];
$md5_url = str_replace( '.phar', '.phar.md5', $download_url );
@@ -322,7 +339,7 @@ public function update( $_, $assoc_args ) {
$php_binary = Utils\get_php_binary();
$process = WP_CLI\Process::create( "{$php_binary} $temp --info {$allow_root}" );
$result = $process->run();
- if ( 0 !== $result->return_code || false === stripos( $result->stdout, 'WP-CLI version:' ) ) {
+ if ( 0 !== $result->return_code || false === stripos( $result->stdout, 'WP-CLI version' ) ) {
$multi_line = explode( PHP_EOL, $result->stderr );
WP_CLI::error_multi_line( $multi_line );
WP_CLI::error( 'The downloaded PHAR is broken, try running wp cli update again.' );
@@ -350,13 +367,16 @@ class_exists( '\cli\Colors' ); // This autoloads \cli\Colors - after we move the
$updated_version = $newest['version'];
}
WP_CLI::success( sprintf( 'Updated WP-CLI to %s.', $updated_version ) );
+ // As the Phar was replaced, we must exit to avoid PHP errors.
+ exit;
}
/**
* Returns update information.
*/
private function get_updates( $assoc_args ) {
- $url = 'https://api.github.com/repos/wp-cli/wp-cli/releases?per_page=100';
+ // Get by last updated descending.
+ $url = 'https://api.github.com/repos/wp-cli/wp-cli/releases?sort=updated&per_page=100';
$options = array(
'timeout' => 30,
@@ -369,13 +389,65 @@ private function get_updates( $assoc_args ) {
$headers['Authorization'] = 'token ' . $github_token;
}
- $response = Utils\http_request( 'GET', $url, null, $headers, $options );
+ $release_data = array();
+ $cache_data = null;
- if ( ! $response->success || 200 !== $response->status_code ) {
- WP_CLI::error( sprintf( 'Failed to get latest version (HTTP code %d).', $response->status_code ) );
+ // See if there's cached data. This is a transient, valid only for `max-age` seconds.
+ $cache = WP_CLI::get_cache();
+ $cache_key = 'github_releases';
+
+ if ( $cache->has( $cache_key ) && ( $cache_data = unserialize( $cache->read( $cache_key ) ) ) ) {
+ // Do some basic integrity checking.
+ if ( ! isset( $cache_data['time'], $cache_data['max_age'], $cache_data['release_data'] )
+ || ! is_int( $cache_data['time'] ) || ! is_int( $cache_data['max_age'] ) || ! is_array( $cache_data['release_data'] ) ) {
+ $cache_data = null;
+ } elseif ( time() <= $cache_data['time'] + $cache_data['max_age'] ) {
+ $release_data = $cache_data['release_data'];
+ }
}
- $release_data = json_decode( $response->body );
+ if ( ! $release_data ) {
+ // No cached transient.
+ $max_age = $time = 0;
+ do {
+ $response = Utils\http_request( 'GET', $url, null, $headers, $options );
+
+ if ( ! $response->success || 200 !== (int) $response->status_code ) {
+ $msg = sprintf( 'Failed to get latest version (HTTP code %d) (%susing GITHUB_TOKEN).', $response->status_code, $github_token ? '' : 'NOT ' );
+ if ( 403 === $response->status_code && $cache_data ) {
+ WP_CLI::warning( $msg . ' - using stale cache data.' );
+ $max_age = 0; // Make sure not to write stale data to cache.
+ $release_data = $cache_data['release_data'];
+ break;
+ }
+ WP_CLI::error( $msg );
+ }
+
+ if ( ! $max_age && isset( $response->headers['cache-control'] ) && preg_match( '/max-age=([0-9]+)/', $response->headers['cache-control'], $matches ) ) {
+ $max_age = (int) $matches[1];
+ if ( empty( $response->headers['date'] ) || false === ( $time = Utils\strtotime_gmt( $response->headers['date'] ) ) ) {
+ $time = time();
+ }
+ }
+
+ // Reduce the data to what's used.
+ $release_data = array_merge( $release_data, array_map(
+ function ( $v ) {
+ return (object) array(
+ 'tag_name' => $v->tag_name,
+ 'assets' => array( (object) array( 'browser_download_url' => $v->assets[0]->browser_download_url ) ),
+ );
+ }, json_decode( $response->body ) )
+ );
+
+ // Loop while have paged data ("next" link).
+ } while ( ! empty( $response->headers['link'] ) && preg_match( '/<([^>]+)>; rel="next"/', $response->headers['link'], $matches ) && ( $url = $matches[1] ) );
+
+ if ( $max_age ) {
+ $cache->write( $cache_key, serialize( compact( 'max_age', 'time', 'release_data' ) ) );
+ }
+ }
+ unset( $cache_data, $response );
$updates = array(
'major' => false,
@@ -421,7 +493,7 @@ private function get_updates( $assoc_args ) {
if ( empty( $updates ) && preg_match( '#-alpha-(.+)$#', WP_CLI_VERSION, $matches ) ) {
$version_url = 'https://raw.githubusercontent.com/wp-cli/builds/gh-pages/phar/NIGHTLY_VERSION';
$response = Utils\http_request( 'GET', $version_url );
- if ( ! $response->success || 200 !== $response->status_code ) {
+ if ( ! $response->success || 200 !== (int) $response->status_code ) {
WP_CLI::error( sprintf( 'Failed to get current nightly version (HTTP code %d)', $response->status_code ) );
}
$nightly_version = trim( $response->body );
diff --git a/php/dispatcher.php b/php/dispatcher.php
index bd11a3927e..90b8761dc7 100644
--- a/php/dispatcher.php
+++ b/php/dispatcher.php
@@ -5,8 +5,8 @@
/**
* Get the path to a command, e.g. "core download"
*
- * @param WP_CLI\Dispatcher\Subcommand $command
- * @return string
+ * @param CompositeCommand $command
+ * @return array
*/
function get_path( $command ) {
$path = array();
diff --git a/php/utils-wp.php b/php/utils-wp.php
index b7ec062e9a..96b3aaba37 100644
--- a/php/utils-wp.php
+++ b/php/utils-wp.php
@@ -277,6 +277,7 @@ function wp_get_cache_type() {
*
* @access public
* @category System
+ * @deprecated 1.5.0
*/
function wp_clear_object_cache() {
global $wpdb, $wp_object_cache;
@@ -287,13 +288,19 @@ function wp_clear_object_cache() {
return;
}
- $wp_object_cache->group_ops = array();
- $wp_object_cache->stats = array();
- $wp_object_cache->memcache_debug = array();
- $wp_object_cache->cache = array();
-
- if ( is_callable( $wp_object_cache, '__remoteset' ) ) {
- $wp_object_cache->__remoteset(); // important
+ // The following are Memcached (Redux) plugin specific (see https://core.trac.wordpress.org/ticket/31463).
+ if ( isset( $wp_object_cache->group_ops ) ) {
+ $wp_object_cache->group_ops = array();
+ }
+ if ( isset( $wp_object_cache->stats ) ) {
+ $wp_object_cache->stats = array();
+ }
+ if ( isset( $wp_object_cache->memcache_debug ) ) {
+ $wp_object_cache->memcache_debug = array();
+ }
+ // Used by `WP_Object_Cache` also.
+ if ( isset( $wp_object_cache->cache ) ) {
+ $wp_object_cache->cache = array();
}
}
@@ -309,117 +316,58 @@ function wp_clear_object_cache() {
function wp_get_table_names( $args, $assoc_args = array() ) {
global $wpdb;
- // Prioritize any supplied $args as tables
- if ( ! empty( $args ) ) {
- $new_tables = array();
- $get_tables_for_glob = function( $glob ) {
- global $wpdb;
- static $all_tables = array();
- if ( ! $all_tables ) {
- $all_tables = $wpdb->get_col( 'SHOW TABLES' );
- }
- $tables = array();
- foreach ( $all_tables as $table ) {
- if ( fnmatch( $glob, $table ) ) {
- $tables[] = $table;
- }
- }
- return $tables;
- };
- foreach ( $args as $key => $table ) {
- if ( false !== strpos( $table, '*' ) || false !== strpos( $table, '?' ) ) {
- $expanded_tables = $get_tables_for_glob( $table );
- if ( empty( $expanded_tables ) ) {
- \WP_CLI::error( "Couldn't find any tables matching: {$table}" );
- }
- $new_tables = array_merge( $new_tables, $expanded_tables );
- } else {
- $new_tables[] = $table;
- }
- }
- return $new_tables;
- }
-
- // Fall back to flag if no tables were passed
- $table_type = 'WordPress';
- if ( get_flag_value( $assoc_args, 'network' ) ) {
- $table_type = 'network';
- }
- if ( get_flag_value( $assoc_args, 'all-tables-with-prefix' ) ) {
- $table_type = 'all-tables-with-prefix';
- }
+ $tables = array();
if ( get_flag_value( $assoc_args, 'all-tables' ) ) {
- $table_type = 'all-tables';
- }
-
- $network = 'network' == $table_type;
+ $tables = $wpdb->get_col( 'SHOW TABLES' );
- if ( 'all-tables' == $table_type ) {
- return $wpdb->get_col( 'SHOW TABLES' );
- }
+ } elseif ( get_flag_value( $assoc_args, 'all-tables-with-prefix' ) ) {
+ $tables = $wpdb->get_col( $wpdb->prepare( 'SHOW TABLES LIKE %s', esc_like( $wpdb->get_blog_prefix() ) . '%' ) );
- $prefix = $network ? $wpdb->base_prefix : $wpdb->prefix;
- // '_' is a special wildcard for MySQL LIKE queries
- // so it needs to be escaped with '\', but then '\' needs to be escaped as well
- $sql_prefix = str_replace( '_', '\\_', $prefix );
- $matching_tables = $wpdb->get_col( $wpdb->prepare( 'SHOW TABLES LIKE %s', $sql_prefix . '%' ) );
-
- if ( 'all-tables-with-prefix' == $table_type ) {
- return $matching_tables;
- }
-
- $filter_sitecategories = function( $matching_tables ) {
- global $wpdb;
- // Only include sitecategories when it's actually enabled.
- if ( ! global_terms_enabled() ) {
- $key = array_search( $wpdb->sitecategories, $matching_tables );
- if ( false !== $key ) {
- unset( $matching_tables[ $key ] );
+ } else {
+ $scope = get_flag_value( $assoc_args, 'scope', 'all' );
+
+ // Note: BC change 1.5.0, taking scope into consideration for network also.
+ if ( get_flag_value( $assoc_args, 'network' ) && is_multisite() ) {
+ $network_global_scope = in_array( $scope, array( 'all', 'global', 'ms_global' ), true ) ? ( 'all' === $scope ? 'global' : $scope ) : '';
+ $wp_tables = array_values( $wpdb->tables( $network_global_scope ) );
+ if ( in_array( $scope, array( 'all', 'blog' ), true ) ) {
+ // Do directly for compat with old WP versions. Note: private, deleted, archived sites are not excluded.
+ $blog_ids = $wpdb->get_col( "SELECT blog_id FROM $wpdb->blogs WHERE site_id = $wpdb->siteid" );
+ foreach ( $blog_ids as $blog_id ) {
+ $wp_tables = array_merge( $wp_tables, array_values( $wpdb->tables( 'blog', true /*prefix*/, $blog_id ) ) );
+ }
}
+ } else {
+ $wp_tables = array_values( $wpdb->tables( $scope ) );
}
- return $matching_tables;
- };
- if ( $scope = get_flag_value( $assoc_args, 'scope' ) ) {
- $matching_tables = $wpdb->tables( $scope );
- $matching_tables = $filter_sitecategories( $matching_tables );
- return $matching_tables;
- }
-
- $allowed_tables = array();
- $allowed_table_types = array( 'tables', 'global_tables' );
- if ( $network ) {
- $allowed_table_types[] = 'ms_global_tables';
- }
- foreach ( $allowed_table_types as $table_type ) {
- foreach ( $wpdb->$table_type as $table ) {
- $allowed_tables[] = $prefix . $table;
+ if ( ! global_terms_enabled() ) {
+ // Only include sitecategories when it's actually enabled.
+ $wp_tables = array_values( array_diff( $wp_tables, array( $wpdb->sitecategories ) ) );
}
- }
- // Given our matching tables, also allow site-specific tables on the network
- foreach ( $matching_tables as $key => $matched_table ) {
-
- if ( in_array( $matched_table, $allowed_tables ) ) {
- continue;
- }
+ // Note: BC change 1.5.0, tables are sorted (via TABLES view).
+ // @codingStandardsIgnoreLine
+ $tables = $wpdb->get_col( sprintf( "SHOW TABLES WHERE %s IN ('%s')", esc_sql_ident( 'Tables_in_' . $wpdb->dbname ), implode( "', '", $wpdb->_escape( $wp_tables ) ) ) );
+ }
- if ( $network ) {
- $valid_table = false;
- foreach ( array_merge( $wpdb->tables, $wpdb->old_tables ) as $maybe_site_table ) {
- if ( preg_match( "#{$prefix}([\d]+)_{$maybe_site_table}#", $matched_table ) ) {
- $valid_table = true;
- }
- }
- if ( $valid_table ) {
- continue;
+ // Filter by `$args`.
+ if ( $args ) {
+ $args_tables = array();
+ foreach ( $args as $arg ) {
+ if ( false !== strpos( $arg, '*' ) || false !== strpos( $arg, '?' ) ) {
+ $args_tables = array_merge( $args_tables, array_filter( $tables, function ( $v ) use ( $arg ) {
+ return fnmatch( $arg, $v );
+ } ) );
+ } else {
+ $args_tables[] = $arg;
}
}
-
- unset( $matching_tables[ $key ] );
-
+ $args_tables = array_values( array_unique( $args_tables ) );
+ if ( ! ( $tables = array_values( array_intersect( $tables, $args_tables ) ) ) ) {
+ \WP_CLI::error( sprintf( "Couldn't find any tables matching: %s", implode( ' ', $args ) ) );
+ }
}
- $filter_sitecategories( $matching_tables );
- return array_values( $matching_tables );
+ return $tables;
}
diff --git a/php/utils.php b/php/utils.php
index be27ede7a1..b67a55e1e7 100644
--- a/php/utils.php
+++ b/php/utils.php
@@ -350,7 +350,8 @@ function pick_fields( $item, $fields ) {
* @access public
* @category Input
*
- * @param string $content Some form of text to edit (e.g. post content)
+ * @param string $input Some form of text to edit (e.g. post content)
+ * @param string $filename Optional. File name to use as base for temporary file. Default 'WP-CLI'.
* @return string|bool Edited text, if file is saved from editor; false, if no change to file.
*/
function launch_editor_for_input( $input, $filename = 'WP-CLI' ) {
@@ -362,7 +363,7 @@ function launch_editor_for_input( $input, $filename = 'WP-CLI' ) {
do {
$tmpfile = basename( $filename );
$tmpfile = preg_replace( '|\.[^.]*$|', '', $tmpfile );
- $tmpfile .= '-' . substr( md5( mt_rand() ), 0, 6 );
+ $tmpfile .= '-' . substr( md5( (string) mt_rand() ), 0, 6 );
$tmpfile = $tmpdir . $tmpfile . '.tmp';
$fp = fopen( $tmpfile, 'xb' );
if ( ! $fp && is_writable( $tmpdir ) && file_exists( $tmpfile ) ) {
@@ -772,6 +773,30 @@ function trailingslashit( $string ) {
return rtrim( $string, '/\\' ) . '/';
}
+/**
+ * Normalizes directory separators to slashes.
+ *
+ * @access public
+ * @category System
+ *
+ * @param string $path Path to convert.
+ *
+ * @return string Path with all backslashes replaced by slashes.
+ */
+function normalize_directory_separators( $path ) {
+ return str_replace( '\\', '/', $path );
+}
+
+/**
+ * Convert Windows EOLs to *nix.
+ *
+ * @param string $str String to convert.
+ * @return string String with carriage return / newline pairs reduced to newlines.
+ */
+function normalize_eols( $str ) {
+ return str_replace( "\r\n", "\n", $str );
+}
+
/**
* Get the system's temp directory. Warns user if it isn't writable.
*
@@ -788,7 +813,7 @@ function get_temp_dir() {
}
// `sys_get_temp_dir()` introduced PHP 5.2.1. Will always return something.
- $temp = trailingslashit( sys_get_temp_dir() );
+ $temp = trailingslashit( normalize_directory_separators( sys_get_temp_dir() ) );
if ( ! is_writable( $temp ) ) {
\WP_CLI::warning( "Temp directory isn't writable: {$temp}" );
@@ -1101,7 +1126,9 @@ function glob_brace( $pattern, $dummy_flags = null ) {
function get_suggestion( $target, array $options, $threshold = 2 ) {
$suggestion_map = array(
+ 'add' => 'create',
'check' => 'check-update',
+ 'capability' => 'cap',
'clear' => 'flush',
'decrement' => 'decr',
'del' => 'delete',
@@ -1117,6 +1144,7 @@ function get_suggestion( $target, array $options, $threshold = 2 ) {
'regen' => 'regenerate',
'rep' => 'replace',
'repl' => 'replace',
+ 'trash' => 'delete',
'v' => 'version',
);
@@ -1127,6 +1155,7 @@ function get_suggestion( $target, array $options, $threshold = 2 ) {
if ( empty( $options ) ) {
return '';
}
+ $levenshtein = array();
foreach ( $options as $option ) {
$distance = levenshtein( $option, $target );
$levenshtein[ $option ] = $distance;
@@ -1247,6 +1276,30 @@ function check_proc_available( $context = null, $return = false ) {
return true;
}
+/**
+ * Wrapper around strtotime() that always interprets the string with a default timezone of UTC.
+ *
+ * @param string $str A date/time string.
+ * @param int $now Optional. The timestamp which is used as a base for the calculation of relative dates.
+ *
+ * @return int|bool Returns a timestamp on success, false otherwise.
+ */
+function strtotime_gmt( $str, $now = null ) {
+ $get = date_default_timezone_get();
+ if ( 'UTC' !== $get ) {
+ date_default_timezone_set( 'UTC' );
+ }
+ if ( null === $now ) {
+ $ret = strtotime( $str );
+ } else {
+ $ret = strtotime( $str, $now );
+ }
+ if ( 'UTC' !== $get ) {
+ date_default_timezone_set( $get );
+ }
+ return $ret;
+}
+
/**
* Returns past tense of verb, with limited accuracy. Only regular verbs catered for, apart from "reset".
*
@@ -1323,12 +1376,21 @@ function get_php_binary() {
* @param array $env Array of environment variables.
* @param array $other_options Array of additional options (Windows only).
*
- * @return string Command stripped of any environment variable settings.
+ * @return resource|false Returns resource representing the process on success; false on failure.
*/
function proc_open_compat( $cmd, $descriptorspec, &$pipes, $cwd = null, $env = null, $other_options = null ) {
if ( is_windows() ) {
// Need to encompass the whole command in double quotes - PHP bug https://bugs.php.net/bug.php?id=49139
$cmd = '"' . _proc_open_compat_win_env( $cmd, $env ) . '"';
+ // If environment array set, make sure certain entries are set otherwise can cause Windows `getaddrinfo()` and `mysqli_connect()` to crap out.
+ if ( null !== $env ) {
+ $env_names = array( 'HOME', 'PATH', 'SYSTEMROOT', 'TERM', 'TMP' ); // Probably only SYSTEMROOT and TMP are needed, but the others can't hurt.
+ foreach ( $env_names as $env_name ) {
+ if ( ! isset( $env[ $env_name ] ) && ( $env_val = getenv( $env_name ) ) ) {
+ $env[ $env_name ] = $env_val;
+ }
+ }
+ }
}
return proc_open( $cmd, $descriptorspec, $pipes, $cwd, $env, $other_options );
}
@@ -1375,6 +1437,24 @@ function esc_like( $text ) {
return addcslashes( $text, '_%\\' );
}
+/**
+ * Escapes (backticks) MySQL identifiers (aka schema object names) - i.e. column names, table names, and database/index/alias/view etc names.
+ * See https://dev.mysql.com/doc/refman/5.5/en/identifiers.html
+ *
+ * @param string|array $idents A single identifier or an array of identifiers.
+ * @return string|array An escaped string if given a string, or an array of escaped strings if given an array of strings.
+ */
+function esc_sql_ident( $idents ) {
+ $backtick = function ( $v ) {
+ // Escape any backticks in the identifier by doubling.
+ return '`' . str_replace( '`', '``', $v ) . '`';
+ };
+ if ( is_string( $idents ) ) {
+ return $backtick( $idents );
+ }
+ return array_map( $backtick, $idents );
+}
+
/**
* Check whether a given string is a valid JSON representation.
*
@@ -1385,7 +1465,7 @@ function esc_like( $text ) {
* @return bool Whether the provided string is a valid JSON representation.
*/
function is_json( $argument, $ignore_scalars = true ) {
- if ( empty( $argument ) || ! is_string( $argument ) ) {
+ if ( ! is_string( $argument ) || '' === $argument ) {
return false;
}
diff --git a/phpcs.xml.dist b/phpcs.xml.dist
index e34339ca53..8d83f89d54 100644
--- a/phpcs.xml.dist
+++ b/phpcs.xml.dist
@@ -18,21 +18,23 @@
*/tests/*
*/utils/*
*/vendor/*
+ */.phan/*
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
diff --git a/templates/man.mustache b/templates/man.mustache
index fbb2e9bd6b..b04c5ffb6f 100644
--- a/templates/man.mustache
+++ b/templates/man.mustache
@@ -24,5 +24,4 @@
{{#subcommands}}
{{.}}
{{/subcommands}}
-
{{/has-subcommands}}
diff --git a/tests/test-behat-tags.php b/tests/test-behat-tags.php
index 11ea159de2..159226e11c 100644
--- a/tests/test-behat-tags.php
+++ b/tests/test-behat-tags.php
@@ -121,8 +121,8 @@ function test_behat_tags_extension() {
if ( ! extension_loaded( 'imagick' ) ) {
$expecteds[] = '~@require-extension-imagick';
}
- if ( ! extension_loaded( 'intl' ) ) {
- $expecteds[] = '~@require-extension-intl';
+ if ( ! extension_loaded( 'curl' ) ) {
+ $expecteds[] = '~@require-extension-curl';
}
$expected = '--tags=' . implode( '&&', array_merge( array( '~@github-api', '~@broken' ), $expecteds ) );
$output = exec( "cd {$this->temp_dir}; php $behat_tags" );
diff --git a/tests/test-doc-parser.php b/tests/test-doc-parser.php
index 7fdf261c06..a751189f35 100644
--- a/tests/test-doc-parser.php
+++ b/tests/test-doc-parser.php
@@ -40,6 +40,7 @@ function test_no_longdesc() {
);
$this->assertEquals( 'Rock and roll!', $doc->get_shortdesc() );
+ error_log( __FUNCTION__ . " longdesc=" . $doc->get_longdesc() . "" );
$this->assertEquals( '', $doc->get_longdesc() );
$this->assertEquals( '', $doc->get_synopsis() );
$this->assertEquals( 'rock-on', $doc->get_tag('alias') );
diff --git a/tests/test-extractor.php b/tests/test-extractor.php
index 330b993902..209fc419c0 100644
--- a/tests/test-extractor.php
+++ b/tests/test-extractor.php
@@ -7,20 +7,23 @@ class Extractor_Test extends PHPUnit_Framework_TestCase {
static $copy_overwrite_files_prefix = 'wp-cli-test-utils-copy-overwrite-files-';
- static $expected_wp = array(
- 'index1.php',
- 'license2.php',
- 'wp-admin/',
- 'wp-admin/about3.php',
- 'wp-admin/includes/',
- 'wp-admin/includes/file4.php',
- 'wp-admin/widgets5.php',
- 'wp-config6.php',
- 'wp-includes/',
- 'wp-includes/file7.php',
- 'xmlrpc8.php',
+ static $expected_top = array(
+ 'wordpress/',
+ 'wordpress/index1.php',
+ 'wordpress/license2.php',
+ 'wordpress/wp-admin/',
+ 'wordpress/wp-admin/about3.php',
+ 'wordpress/wp-admin/includes/',
+ 'wordpress/wp-admin/includes/file4.php',
+ 'wordpress/wp-admin/widgets5.php',
+ 'wordpress/wp-config6.php',
+ 'wordpress/wp-includes/',
+ 'wordpress/wp-includes/file7.php',
+ 'wordpress/xmlrpc8.php',
);
+ static $expected_wp = null;
+
static $logger = null;
static $prev_logger = null;
@@ -35,6 +38,13 @@ public function setUp() {
self::$logger = new \WP_CLI\Loggers\Execution;
WP_CLI::set_logger( self::$logger );
+ // Init expected_wp.
+ if ( null === self::$expected_wp ) {
+ self::$expected_wp = array_values( array_filter( array_map( function ( $v ) {
+ return substr( $v, strlen( 'wordpress/' ) );
+ }, self::$expected_top ) ) );
+ }
+
// Remove any failed tests detritus.
$temp_dirs = Utils\get_temp_dir() . self::$copy_overwrite_files_prefix . '*';
foreach ( glob( $temp_dirs ) as $temp_dir ) {
@@ -55,10 +65,6 @@ public function test_rmdir() {
$this->assertTrue( is_dir( $wp_dir ) );
Extractor::rmdir( $wp_dir );
$this->assertFalse( file_exists( $wp_dir ) );
-
- $this->assertTrue( is_dir( $temp_dir ) );
- Extractor::rmdir( $temp_dir );
- $this->assertFalse( file_exists( $temp_dir ) );
}
public function test_err_rmdir() {
@@ -77,12 +83,80 @@ public function test_copy_overwrite_files() {
$dest_dir = $temp_dir . '/dest';
+ // Top level src dir, no strip_components.
+
+ Extractor::copy_overwrite_files( $src_dir, $dest_dir );
+
+ $files = self::recursive_scandir( $dest_dir );
+
+ $this->assertSame( self::$expected_top, $files );
+ $this->assertTrue( empty( self::$logger->stderr ) );
+ Extractor::rmdir( $dest_dir );
+
+ // Wordpress dir, no strip_components.
+
Extractor::copy_overwrite_files( $wp_dir, $dest_dir );
$files = self::recursive_scandir( $dest_dir );
$this->assertSame( self::$expected_wp, $files );
$this->assertTrue( empty( self::$logger->stderr ) );
+ Extractor::rmdir( $dest_dir );
+
+ // Top level src dir, strip_components 1.
+
+ Extractor::copy_overwrite_files( $src_dir, $dest_dir, 1 /*strip_components*/ );
+
+ $files = self::recursive_scandir( $dest_dir );
+
+ $this->assertSame( self::$expected_wp, $files );
+ $this->assertTrue( empty( self::$logger->stderr ) );
+ Extractor::rmdir( $dest_dir );
+
+ // Wordpress dir, strip_components 1.
+
+ Extractor::copy_overwrite_files( $wp_dir, $dest_dir, 1 /*strip_components*/ );
+
+ $files = self::recursive_scandir( $dest_dir );
+
+ $expected = array(
+ 'about3.php',
+ 'file7.php',
+ 'includes/',
+ 'includes/file4.php',
+ 'widgets5.php',
+ );
+ $this->assertSame( $expected, $files );
+
+ // Top level src dir, strip_components 2 (same as Wordpress dir, strip_components 1).
+
+ Extractor::copy_overwrite_files( $src_dir, $dest_dir, 2 /*strip_components*/ );
+
+ $files = self::recursive_scandir( $dest_dir );
+
+ $expected = array(
+ 'about3.php',
+ 'file7.php',
+ 'includes/',
+ 'includes/file4.php',
+ 'widgets5.php',
+ );
+ $this->assertSame( $expected, $files );
+ $this->assertTrue( empty( self::$logger->stderr ) );
+ Extractor::rmdir( $dest_dir );
+
+ // Top level src dir, strip_components 3.
+
+ Extractor::copy_overwrite_files( $src_dir, $dest_dir, 3 /*strip_components*/ );
+
+ $files = self::recursive_scandir( $dest_dir );
+
+ $expected = array(
+ 'file4.php',
+ );
+ $this->assertSame( $expected, $files );
+ $this->assertTrue( empty( self::$logger->stderr ) );
+ Extractor::rmdir( $dest_dir );
// Clean up.
Extractor::rmdir( $temp_dir );
@@ -104,6 +178,8 @@ public function test_extract_tarball() {
$this->markTestSkipped( 'tar not installed.' );
}
+ $extractor_shell = getenv( 'WP_CLI_TEST_EXTRACTOR_SHELL' );
+
list( $temp_dir, $src_dir, $wp_dir ) = self::create_test_directory_structure();
$tarball = $temp_dir . '/test.tar.gz';
@@ -112,25 +188,55 @@ public function test_extract_tarball() {
// Create test tarball.
$output = array();
$return_var = -1;
- // Need --force-local for Windows to avoid "C:" being interpreted as being on remote machine.
- exec( Utils\esc_cmd( 'tar czvf %1$s --force-local --directory=%2$s/src wordpress', $tarball, $temp_dir ), $output, $return_var );
+ // Need --force-local for Windows to avoid "C:" being interpreted as being on remote machine, and redirect for Mac as outputs verbosely on STDERR.
+ $cmd = 'tar czvf %1$s' . ( Utils\is_windows() ? ' --force-local' : '' ) . ' --directory=%2$s/src wordpress 2>&1';
+ exec( Utils\esc_cmd( $cmd, $tarball, $temp_dir ), $output, $return_var );
$this->assertSame( 0, $return_var );
$this->assertFalse( empty( $output ) );
+
+ // Normalize (Mac) output.
+ $output = array_map( function ( $v ) {
+ if ( 'a ' === substr( $v, 0, 2 ) ) {
+ $v = substr( $v, 2 );
+ }
+ if ( '/' !== substr( $v, -1 ) && false === strpos( $v, '.' ) ) {
+ $v .= '/';
+ }
+ return $v;
+ }, $output );
sort( $output );
+
$this->assertSame( self::recursive_scandir( $src_dir ), $output );
// Test.
+ putenv( 'WP_CLI_TEST_EXTRACTOR_SHELL' );
+ Extractor::extract( $tarball, $dest_dir );
+
+ $files = self::recursive_scandir( $dest_dir );
+ $this->assertSame( self::$expected_wp, $files );
+ $this->assertTrue( empty( self::$logger->stderr ) );
+ Extractor::rmdir( $dest_dir );
+
+ self::$logger->stderr = self::$logger->stdout = ''; // Reset logger.
+
+ putenv( 'WP_CLI_TEST_EXTRACTOR_SHELL=1' );
Extractor::extract( $tarball, $dest_dir );
$files = self::recursive_scandir( $dest_dir );
$this->assertSame( self::$expected_wp, $files );
$this->assertTrue( empty( self::$logger->stderr ) );
+ Extractor::rmdir( $dest_dir );
// Clean up.
Extractor::rmdir( $temp_dir );
+
+ putenv( false === $extractor_shell ? 'WP_CLI_TEST_EXTRACTOR_SHELL' : "WP_CLI_TEST_EXTRACTOR_SHELL=$extractor_shell" );
}
public function test_err_extract_tarball() {
+ $extractor_shell = getenv( 'WP_CLI_TEST_EXTRACTOR_SHELL' );
+
+ putenv( 'WP_CLI_TEST_EXTRACTOR_SHELL' );
// Non-existent.
$msg = '';
try {
@@ -139,7 +245,7 @@ public function test_err_extract_tarball() {
$msg = $e->getMessage();
}
$this->assertTrue( false !== strpos( $msg, 'no-such-tar' ) );
- $this->assertTrue( 0 === strpos( self::$logger->stderr, 'Warning: PharData failed' ) );
+ $this->assertTrue( 0 === strpos( self::$logger->stderr, "Warning: Falling back to 'tar xz'. PharData failed" ) );
$this->assertTrue( false !== strpos( self::$logger->stderr, 'no-such-tar' ) );
self::$logger->stderr = self::$logger->stdout = ''; // Reset logger.
@@ -155,8 +261,38 @@ public function test_err_extract_tarball() {
}
unlink( $zero_tar );
$this->assertTrue( false !== strpos( $msg, 'zero-tar' ) );
- $this->assertTrue( 0 === strpos( self::$logger->stderr, 'Warning: PharData failed' ) );
+ $this->assertTrue( 0 === strpos( self::$logger->stderr, "Warning: Falling back to 'tar xz'. PharData failed" ) );
$this->assertTrue( false !== strpos( self::$logger->stderr, 'zero-tar' ) );
+
+ self::$logger->stderr = self::$logger->stdout = ''; // Reset logger.
+
+ putenv( 'WP_CLI_TEST_EXTRACTOR_SHELL=1' );
+ // Non-existent.
+ $msg = '';
+ try {
+ Extractor::extract( 'no-such-tar.tar.gz', 'dest-dir' );
+ } catch ( \Exception $e ) {
+ $msg = $e->getMessage();
+ }
+ $this->assertTrue( false !== strpos( $msg, 'no-such-tar' ) );
+ $this->assertTrue( empty( self::$logger->stderr ) );
+
+ self::$logger->stderr = self::$logger->stdout = ''; // Reset logger.
+
+ // Zero-length.
+ $zero_tar = Utils\get_temp_dir() . 'zero-tar.tar.gz';
+ touch( $zero_tar );
+ $msg = '';
+ try {
+ Extractor::extract( $zero_tar, 'dest-dir' );
+ } catch ( \Exception $e ) {
+ $msg = $e->getMessage();
+ }
+ unlink( $zero_tar );
+ $this->assertTrue( false !== strpos( $msg, 'zero-tar' ) );
+ $this->assertTrue( empty( self::$logger->stderr ) );
+
+ putenv( false === $extractor_shell ? 'WP_CLI_TEST_EXTRACTOR_SHELL' : "WP_CLI_TEST_EXTRACTOR_SHELL=$extractor_shell" );
}
public function test_extract_zip() {
@@ -164,6 +300,8 @@ public function test_extract_zip() {
$this->markTestSkipped( 'ZipArchive not installed.' );
}
+ $extractor_zip_archive = getenv( 'WP_CLI_TEST_EXTRACTOR_ZIP_ARCHIVE' );
+
list( $temp_dir, $src_dir, $wp_dir ) = self::create_test_directory_structure();
$zipfile = $temp_dir . '/test.zip';
@@ -186,14 +324,25 @@ public function test_extract_zip() {
$this->assertTrue( $result );
// Test.
+ putenv( 'WP_CLI_TEST_EXTRACTOR_ZIP_ARCHIVE' );
Extractor::extract( $zipfile, $dest_dir );
$files = self::recursive_scandir( $dest_dir );
$this->assertSame( self::$expected_wp, $files );
$this->assertTrue( empty( self::$logger->stderr ) );
+ Extractor::rmdir( $dest_dir );
+
+ putenv( 'WP_CLI_TEST_EXTRACTOR_ZIP_ARCHIVE=1' );
+ Extractor::extract( $zipfile, $dest_dir );
+
+ $files = self::recursive_scandir( $dest_dir );
+ $this->assertSame( self::$expected_wp, $files );
+ $this->assertTrue( empty( self::$logger->stderr ) );
+ Extractor::rmdir( $dest_dir );
// Clean up.
Extractor::rmdir( $temp_dir );
+ putenv( false === $extractor_zip_archive ? 'WP_CLI_TEST_EXTRACTOR_ZIP_ARCHIVE' : "WP_CLI_TEST_EXTRACTOR_ZIP_ARCHIVE=$extractor_zip_archive" );
}
public function test_err_extract_zip() {
@@ -201,6 +350,41 @@ public function test_err_extract_zip() {
$this->markTestSkipped( 'ZipArchive not installed.' );
}
+ $extractor_zip_archive = getenv( 'WP_CLI_TEST_EXTRACTOR_ZIP_ARCHIVE' );
+
+ putenv( 'WP_CLI_TEST_EXTRACTOR_ZIP_ARCHIVE' );
+ // Non-existent.
+ $msg = '';
+ try {
+ Extractor::extract( 'no-such-zip.zip', 'dest-dir' );
+ } catch ( \Exception $e ) {
+ $msg = $e->getMessage();
+ }
+ $this->assertTrue( false !== strpos( $msg, 'no-such-zip' ) );
+ $this->assertFalse( empty( self::$logger->stderr ) );
+
+ self::$logger->stderr = self::$logger->stdout = ''; // Reset logger.
+
+ // Zero-length - NO error surprisingly with PharData.
+ $zero_zip = Utils\get_temp_dir() . 'zero-zip.zip';
+ $dest_dir = Utils\get_temp_dir() . 'dest-dir';
+ touch( $zero_zip );
+ $msg = '';
+ try {
+ Extractor::extract( $zero_zip, $dest_dir );
+ } catch ( \Exception $e ) {
+ $msg = $e->getMessage();
+ }
+ unlink( $zero_zip );
+ $this->assertTrue( '' === $msg );
+ $this->assertFalse( empty( self::$logger->stderr ) );
+ $this->assertTrue( is_dir( $dest_dir ) );
+ $this->assertSame( array(), self::recursive_scandir( $dest_dir ) );
+ rmdir( $dest_dir );
+
+ self::$logger->stderr = self::$logger->stdout = ''; // Reset logger.
+
+ putenv( 'WP_CLI_TEST_EXTRACTOR_ZIP_ARCHIVE=1' );
// Non-existent.
$msg = '';
try {
@@ -213,18 +397,24 @@ public function test_err_extract_zip() {
self::$logger->stderr = self::$logger->stdout = ''; // Reset logger.
- // Zero-length.
+ // Zero-length - No error surprisingly with ZipArchive either.
$zero_zip = Utils\get_temp_dir() . 'zero-zip.zip';
+ $dest_dir = Utils\get_temp_dir() . 'dest-dir';
touch( $zero_zip );
$msg = '';
try {
- Extractor::extract( $zero_zip, 'dest-dir' );
+ Extractor::extract( $zero_zip, $dest_dir );
} catch ( \Exception $e ) {
$msg = $e->getMessage();
}
unlink( $zero_zip );
- $this->assertTrue( false !== strpos( $msg, 'zero-zip' ) );
+ $this->assertTrue( '' === $msg );
$this->assertTrue( empty( self::$logger->stderr ) );
+ $this->assertTrue( is_dir( $dest_dir ) );
+ $this->assertSame( array(), self::recursive_scandir( $dest_dir ) );
+ rmdir( $dest_dir );
+
+ putenv( false === $extractor_zip_archive ? 'WP_CLI_TEST_EXTRACTOR_ZIP_ARCHIVE' : "WP_CLI_TEST_EXTRACTOR_ZIP_ARCHIVE=$extractor_zip_archive" );
}
public function test_err_extract() {
@@ -246,13 +436,12 @@ private function create_test_directory_structure() {
mkdir( $src_dir );
$wp_dir = $src_dir . '/wordpress';
- mkdir( $wp_dir );
- foreach ( self::$expected_wp as $file ) {
+ foreach ( self::$expected_top as $file ) {
if ( 0 === substr_compare( $file, '/', -1 ) ) {
- mkdir( $wp_dir . '/' . $file );
+ mkdir( $src_dir . '/' . $file );
} else {
- touch( $wp_dir . '/' . $file );
+ touch( $src_dir . '/' . $file );
}
}
diff --git a/tests/test-file-cache.php b/tests/test-file-cache.php
index 1ab58e6fbf..bf1c0128ec 100644
--- a/tests/test-file-cache.php
+++ b/tests/test-file-cache.php
@@ -2,11 +2,50 @@
use WP_CLI\FileCache;
use WP_CLI\Utils;
+use Symfony\Component\Finder\Finder;
require_once dirname( __DIR__ ) . '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/php/class-wp-cli.php';
class FileCacheTest extends PHPUnit_Framework_TestCase {
+ /**
+ * Test that no new classes are loaded in clean() as this can cause problems if it's called in a register_shutdown_function.
+ */
+ public function testFinderLoaded() {
+ $max_size = 32;
+ $ttl = 60;
+
+ $cache_dir = Utils\get_temp_dir() . '/' . uniqid( "wp-cli-test-file-cache", TRUE );
+
+ $cache = new FileCache( $cache_dir, $ttl, $max_size );
+
+ $after_construct_classes = get_declared_classes();
+
+ // Less than time to live file.
+ $cache->write( 'ttl', 'ttl' );
+ touch( $cache_dir . '/ttl', time() - ( $ttl + 1 ) );
+
+ // Greater than max size file.
+ $cache->write( 'max_size', str_repeat( 'm', $max_size + 1 ) );
+
+ // Check no change in loaded classes.
+ $after_write_classes = get_declared_classes();
+ $after_write_diff = array_diff( $after_write_classes, $after_construct_classes );
+ $this->assertEmpty( $after_write_diff );
+
+ $cache->clean();
+
+ // Should be no change in loaded classes.
+ $after_clean_classes = get_declared_classes();
+ $after_clean_diff = array_diff( $after_clean_classes, $after_write_classes );
+ $this->assertEmpty( $after_clean_diff );
+
+ $this->assertFalse( file_exists( $cache_dir . '/max_size' ) );
+ $this->assertFalse( file_exists( $cache_dir . '/ttl' ) );
+
+ rmdir( $cache_dir );
+ }
+
/**
* Test get_root() deals with backslashed directory.
*/
diff --git a/tests/test-make-phar-strip-comments.php b/tests/test-make-phar-strip-comments.php
new file mode 100644
index 0000000000..094d7317bc
--- /dev/null
+++ b/tests/test-make-phar-strip-comments.php
@@ -0,0 +1,198 @@
+assertSame( $source, $actual );
+ $this->assertSame( substr_count( $actual, "\n" ), substr_count( $source, "\n" ) );
+ $expected = <<<'EOD'
+assertSame( $expected, $actual );
+ $this->assertSame( substr_count( $actual, "\n" ), substr_count( $source, "\n" ) );
+
+ }
+
+ /**
+ * Test inline comment behaviour.
+ */
+ function testInlineComments() {
+
+ // Doc comment and inline comments.
+ $source = <<<'EOD'
+assertSame( $expected, $actual );
+ $this->assertSame( substr_count( $actual, "\n" ), substr_count( $source, "\n" ) );
+
+ $expected = <<<'EOD'
+assertSame( $expected, $actual );
+ $this->assertSame( substr_count( $actual, "\n" ), substr_count( $source, "\n" ) );
+ }
+
+ /**
+ * Test keeps copyright comments.
+ */
+ function testCopyright() {
+
+ // Doc comment and inline copyrights.
+ $source = <<<'EOD'
+assertSame( $expected, $actual );
+
+ $expected = <<<'EOD'
+assertSame( $expected, $actual );
+ }
+
+ /**
+ * Test keeps Behat comments.
+ */
+ public function testBehat() {
+
+ $source = <<<'EOD'
+assertSame( $expected, $actual );
+ $this->assertSame( substr_count( $actual, "\n" ), substr_count( $source, "\n" ) );
+ }
+
+}
diff --git a/tests/test-utils.php b/tests/test-utils.php
index 52d7cf4f68..6e4bb19cf9 100644
--- a/tests/test-utils.php
+++ b/tests/test-utils.php
@@ -319,6 +319,17 @@ public function testGetHomeDir() {
putenv( false === $homepath ? 'HOMEPATH' : "HOME=$homepath" );
}
+ public function testStrtotimeGmt() {
+ $get = date_default_timezone_get();
+
+ $date = 'Fri, 30 May 2008 04:20:12';
+
+ date_default_timezone_set( 'America/Godthab' ); // -2h in northern summer.
+ $this->assertSame( strtotime( $date ) - 2 * 60 * 60, Utils\strtotime_gmt( $date ) );
+
+ date_default_timezone_set( $get );
+ }
+
public function testTrailingslashit() {
$this->assertSame( 'a/', Utils\trailingslashit( 'a' ) );
$this->assertSame( 'a/', Utils\trailingslashit( 'a/' ) );
@@ -326,30 +337,12 @@ public function testTrailingslashit() {
$this->assertSame( 'a/', Utils\trailingslashit( 'a\\//\\' ) );
}
+ public function testNormalizeEols() {
+ $this->assertSame( "\na\ra\na\n", Utils\normalize_eols( "\r\na\ra\r\na\r\n" ) );
+ }
+
public function testGetTempDir() {
$this->assertTrue( '/' === substr( Utils\get_temp_dir(), -1 ) );
-
- // INI directive `sys_temp_dir` introduced PHP 5.5.0.
- if ( version_compare( PHP_VERSION, '5.5.0', '>=' ) ) {
-
- // `sys_temp_dir` set to unwritable.
-
- $cmd = 'php ' . escapeshellarg( '-dsys_temp_dir=\\tmp\\' ) . ' php/boot-fs.php --skip-wordpress eval ' . escapeshellarg( 'echo WP_CLI\\Utils\\get_temp_dir();' ) . ' 2>&1';
- $output = array();
- exec( $cmd, $output );
- $output = trim( implode( "\n", $output ) );
- $this->assertTrue( false !== strpos( $output, 'Warning' ) );
- $this->assertTrue( false !== strpos( $output, 'writable' ) );
- $this->assertTrue( false !== strpos( $output, '\\tmp/' ) );
-
- // `sys_temp_dir` unset.
-
- $cmd = 'php ' . escapeshellarg( '-dsys_temp_dir=' ) . ' php/boot-fs.php --skip-wordpress eval ' . escapeshellarg( 'echo WP_CLI\\Utils\\get_temp_dir();' ) . ' 2>&1';
- $output = array();
- exec( $cmd, $output );
- $output = trim( implode( "\n", $output ) );
- $this->assertTrue( '/' === substr( $output, -1 ) );
- }
}
public function testHttpRequestBadAddress() {
@@ -447,38 +440,6 @@ public function testHttpRequestBadCAcert() {
$class_wp_cli_logger->setValue( $prev_logger );
}
- public function testRunMysqlCommandProcDisabled() {
- $err_msg = 'Error: Cannot do \'run_mysql_command\': The PHP functions `proc_open()` and/or `proc_close()` are disabled';
-
- $cmd = 'php -ddisable_functions=proc_open php/boot-fs.php --skip-wordpress eval ' . escapeshellarg( 'WP_CLI\\Utils\\run_mysql_command( null, array() );' ) . ' 2>&1';
- $output = array();
- exec( $cmd, $output );
- $output = trim( implode( "\n", $output ) );
- $this->assertTrue( false !== strpos( $output, $err_msg ) );
-
- $cmd = 'php -ddisable_functions=proc_close php/boot-fs.php --skip-wordpress eval ' . escapeshellarg( 'WP_CLI\\Utils\\run_mysql_command( null, array() );' ) . ' 2>&1';
- $output = array();
- exec( $cmd, $output );
- $output = trim( implode( "\n", $output ) );
- $this->assertTrue( false !== strpos( $output, $err_msg ) );
- }
-
- public function testLaunchEditorForInputProcDisabled() {
- $err_msg = 'Error: Cannot do \'launch_editor_for_input\': The PHP functions `proc_open()` and/or `proc_close()` are disabled';
-
- $cmd = 'php -ddisable_functions=proc_open php/boot-fs.php --skip-wordpress eval ' . escapeshellarg( 'WP_CLI\\Utils\\launch_editor_for_input( null, null );' ) . ' 2>&1';
- $output = array();
- exec( $cmd, $output );
- $output = trim( implode( "\n", $output ) );
- $this->assertTrue( false !== strpos( $output, $err_msg ) );
-
- $cmd = 'php -ddisable_functions=proc_close php/boot-fs.php --skip-wordpress eval ' . escapeshellarg( 'WP_CLI\\Utils\\launch_editor_for_input( null, null );' ) . ' 2>&1';
- $output = array();
- exec( $cmd, $output );
- $output = trim( implode( "\n", $output ) );
- $this->assertTrue( false !== strpos( $output, $err_msg ) );
- }
-
/**
* @dataProvider dataPastTenseVerb
*/
@@ -524,13 +485,16 @@ public function testExpandGlobs( $path, $expected ) {
$dir = __DIR__ . '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/data/expand_globs/';
$expected = array_map( function ( $v ) use ( $dir ) { return $dir . $v; }, $expected );
+ sort( $expected );
putenv( 'WP_CLI_TEST_EXPAND_GLOBS_NO_GLOB_BRACE=0' );
$out = Utils\expand_globs( $dir . $path );
+ sort( $out );
$this->assertSame( $expected, $out );
putenv( 'WP_CLI_TEST_EXPAND_GLOBS_NO_GLOB_BRACE=1' );
$out = Utils\expand_globs( $dir . $path );
+ sort( $out );
$this->assertSame( $expected, $out );
putenv( false === $expand_globs_no_glob_brace ? 'WP_CLI_TEST_EXPAND_GLOBS_NO_GLOB_BRACE' : "WP_CLI_TEST_EXPAND_GLOBS_NO_GLOB_BRACE=$expand_globs_no_glob_brace" );
@@ -707,6 +671,10 @@ public function dataIsJson() {
array( '{"key1":"value1","key2":"value2"}', false, true ),
array( '["value1","value2"]', true, true ),
array( '["value1","value2"]', false, true ),
+ array( '0', true, false ),
+ array( '0', false, true ),
+ array( '', true, false ),
+ array( '', false, false ),
);
}
diff --git a/tests/test-wp-cli.php b/tests/test-wp-cli.php
index 209fef8c73..a2a68f83bd 100644
--- a/tests/test-wp-cli.php
+++ b/tests/test-wp-cli.php
@@ -2,22 +2,6 @@
class WP_CLI_Test extends PHPUnit_Framework_TestCase {
- public function testLaunchProcDisabled() {
- $err_msg = 'Error: Cannot do \'launch\': The PHP functions `proc_open()` and/or `proc_close()` are disabled';
-
- $cmd = 'php -ddisable_functions=proc_open php/boot-fs.php --skip-wordpress eval ' . escapeshellarg( 'WP_CLI::launch( null );' ) . ' 2>&1';
- $output = array();
- exec( $cmd, $output );
- $output = trim( implode( "\n", $output ) );
- $this->assertTrue( false !== strpos( $output, $err_msg ) );
-
- $cmd = 'php -ddisable_functions=proc_close php/boot-fs.php --skip-wordpress eval ' . escapeshellarg( 'WP_CLI::launch( null );' ) . ' 2>&1';
- $output = array();
- exec( $cmd, $output );
- $output = trim( implode( "\n", $output ) );
- $this->assertTrue( false !== strpos( $output, $err_msg ) );
- }
-
public function testGetPHPBinary() {
$this->assertSame( WP_CLI\Utils\get_php_binary(), WP_CLI::get_php_binary() );
}
diff --git a/utils/contrib-list.php b/utils/contrib-list.php
index 5ab696c54e..3abd62de4c 100644
--- a/utils/contrib-list.php
+++ b/utils/contrib-list.php
@@ -149,7 +149,7 @@ private static function get_project_milestone_pull_requests( $project, $mileston
$request_url = false;
// Set $request_url to 'rel="next" if present'
if ( ! empty( $headers['Link'] ) ) {
- $bits = explode( ',', $headers['Link'] );
+ $bits = trim( explode( ',', $headers['Link'] ) );
foreach( $bits as $bit ) {
if ( false !== stripos( $bit, 'rel="next"' ) ) {
$hrefandrel = explode( '; ', $bit );
diff --git a/utils/git-setup-pre-commit-hook b/utils/git-setup-pre-commit-hook
new file mode 100755
index 0000000000..70c1dfedc8
--- /dev/null
+++ b/utils/git-setup-pre-commit-hook
@@ -0,0 +1,32 @@
+#!/bin/bash
+#
+# Setup Git pre-commit hook.
+#
+
+# stop when composer.json file is not found
+if [[ ! -f "composer.json" ]]; then
+ echo "unable to locate composer.json file."
+ exit 1
+fi
+
+# determine the phpcs binary location
+if [[ -f "vendor/bin/phpcs" ]]; then
+ phpcs_bin="./vendor/bin/phpcs"
+elif [[ -n $COMPOSER_BIN_DIR && -f "$COMPOSER_BIN_DIR/phpcs" ]]; then
+ phpcs_bin="./$COMPOSER_BIN_DIR/phpcs"
+elif [[ -n $COMPOSER_VENDOR_DIR && -f "$COMPOSER_VENDOR_DIR/bin/phpcs" ]]; then
+ phpcs_bin="./$COMPOSER_VENDOR_DIR/bin/phpcs"
+else
+ echo "pre-commit hook: unable to locate phpcs binary file."
+ exit
+fi
+
+# create the pre-commit file or notify to add command if it already exists
+pre_commit_file="$(git rev-parse --git-dir)/hooks/pre-commit"
+
+if [[ ! -f "$pre_commit_file" ]]; then
+ echo -e "#!/bin/bash\nset -ex\n$phpcs_bin" > $pre_commit_file
+ chmod +x $pre_commit_file
+elif ! grep -q "phpcs" $pre_commit_file; then
+ echo -e "hook file already exists: $pre_commit_file\n\nplease add the below command to your pre-commit file:\n\n$phpcs_bin"
+fi
diff --git a/utils/make-phar-strip-comments.php b/utils/make-phar-strip-comments.php
new file mode 100644
index 0000000000..beb9ebd686
--- /dev/null
+++ b/utils/make-phar-strip-comments.php
@@ -0,0 +1,32 @@
+parse_args( array_slice( $GLOBALS['argv'], 1 ) );
if ( ! isset( $args[0] ) || empty( $args[0] ) ) {
- echo "usage: php -dphar.readonly=0 $argv[0] [--quiet] [--version=same|patch|minor|major|x.y.z] [--store-version]\n";
+ fwrite( STDERR, "usage: php -dphar.readonly=0 $argv[0] [--quiet] [--version=same|patch|minor|major|x.y.z] [--store-version] [--build=cli]" . PHP_EOL );
exit(1);
}
@@ -50,8 +51,29 @@
function add_file( $phar, $path ) {
$key = str_replace( WP_CLI_BASE_PATH, '', $path );
- if ( !BE_QUIET )
- echo "$key - $path\n";
+ if ( ! BE_QUIET ) {
+ echo "$key - $path" . PHP_EOL;
+ }
+
+ // Warning: needs to be synced with ScaffoldPackageCommand::package_tests() `$copy_source[ $wp_cli_root ]`.
+ static $scaffold_package_phps = array(
+ 'features/bootstrap/FeatureContext.php' => true,
+ 'features/bootstrap/support.php' => true,
+ 'php/WP_CLI/Process.php' => true,
+ 'php/WP_CLI/ProcessRun.php' => true,
+ 'php/utils.php' => true,
+ 'ci/behat-tags.php' => true,
+ 'features/steps/given.php' => true,
+ 'features/steps/when.php' => true,
+ 'features/steps/then.php' => true,
+ 'features/extra/no-mail.php' => true,
+ );
+
+ $file_contents = file_get_contents( $path );
+ if ( 0 === substr_compare( $path, '.php', -4 ) && ! isset( $scaffold_package_phps[ substr( $key, 1 ) ] ) ) { // `substr()` to remove initial slash.
+ $is_wp_cli_command = preg_match( '/\/(?:php\/commands|[^\/]+?-command\/src)\//', $path );
+ $file_contents = make_phar_strip_comments( $file_contents, $is_wp_cli_command /*keep_doc_comments*/ );
+ }
$basename = basename( $path );
if ( 0 === strpos( $basename, 'autoload_' ) && preg_match( '/(?:classmap|files|namespaces|psr4|static)\.php$/', $basename ) ) {
@@ -60,11 +82,11 @@ function add_file( $phar, $path ) {
if ( null === $strip_res ) {
if ( 'cli' === BUILD ) {
$strips = array(
- '\/(?:behat|composer|gherkin)\/src',
+ '\/(?:behat|composer|gherkin)\/src\/',
'\/phpunit\/',
- '\/nb\/oxymel',
+ '\/nb\/oxymel\/',
'-command\/src\/',
- '\/wp-cli\/[^\n]+-command\/',
+ '\/wp-cli\/(?:[^\n]+?-command|wp-config-transformer)\/',
'\/symfony\/(?!finder|polyfill-mbstring)[^\/]+\/',
'\/(?:dealerdirect|squizlabs|wimg)\/',
);
@@ -82,21 +104,69 @@ function add_file( $phar, $path ) {
return '/^[^,\n]+?' . $v . '[^,\n]+?, *\n/m';
}, $strips );
}
- $phar[ $key ] = preg_replace( $strip_res, '', file_get_contents( $path ) );
+ $phar[ $key ] = preg_replace( $strip_res, '', $file_contents );
} else {
- $phar[ $key ] = file_get_contents( $path );
+ $phar[ $key ] = $file_contents;
}
}
function set_file_contents( $phar, $path, $content ) {
$key = str_replace( WP_CLI_BASE_PATH, '', $path );
- if ( !BE_QUIET )
- echo "$key - $path\n";
+ if ( ! BE_QUIET ) {
+ echo "$key - $path" . PHP_EOL;
+ }
$phar[ $key ] = $content;
}
+function get_composer_versions( $current_version ) {
+ $composer_lock_path = WP_CLI_ROOT . '/composer.lock';
+ if ( ! ( $get_composer_lock = file_get_contents( $composer_lock_path ) ) || ! ( $composer_lock = json_decode( $get_composer_lock, true ) ) ) {
+ fwrite( STDERR, sprintf( "Warning: Failed to read '%s'." . PHP_EOL, $composer_lock_path ) );
+ return '';
+ }
+ if ( ! isset( $composer_lock['packages'] ) ) {
+ fwrite( STDERR, sprintf( "Warning: No packages in '%s'." . PHP_EOL, $composer_lock_path ) );
+ return '';
+ }
+ $vendor_versions = array( implode( ' ', array( 'wp-cli/wp-cli', $current_version, date( 'c' ) ) ) );
+ $missing_names = $missing_versions = $missing_references = 0;
+ foreach ( $composer_lock['packages'] as $package ) {
+ if ( isset( $package['name'] ) ) {
+ $vendor_version = array( $package['name'] );
+ if ( isset( $package['version'] ) ) {
+ $vendor_version[] = $package['version'];
+ } else {
+ $vendor_version[] = 'unknown_version';
+ $missing_versions++;
+ }
+ if ( isset( $package['source'] ) && isset( $package['source']['reference'] ) ) {
+ $vendor_version[] = $package['source']['reference'];
+ } elseif( isset( $package['dist'] ) && isset( $package['dist']['reference'] ) ) {
+ $vendor_version[] = $package['dist']['reference'];
+ } else {
+ $vendor_version[] = 'unknown_reference';
+ $missing_references++;
+ }
+ $vendor_versions[] = implode( ' ', $vendor_version );
+ } else {
+ $vendor_versions[] = implode( ' ', array( 'unknown_package', 'unknown_version', 'unknown_reference' ) );
+ $missing_names++;
+ }
+ }
+ if ( $missing_names ) {
+ fwrite( STDERR, sprintf( "Warning: %d package names missing from '%s'." . PHP_EOL, $missing_names, $composer_lock_path ) );
+ }
+ if ( $missing_versions ) {
+ fwrite( STDERR, sprintf( "Warning: %d package versions missing from '%s'." . PHP_EOL, $missing_versions, $composer_lock_path ) );
+ }
+ if ( $missing_references ) {
+ fwrite( STDERR, sprintf( "Warning: %d package references missing from '%s'." . PHP_EOL, $missing_references, $composer_lock_path ) );
+ }
+ return implode( "\n", $vendor_versions );
+}
+
if ( file_exists( DEST_PATH ) ) {
unlink( DEST_PATH );
}
@@ -149,6 +219,7 @@ function set_file_contents( $phar, $path, $content ) {
->in(WP_CLI_VENDOR_DIR . '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/symfony/filesystem')
->in(WP_CLI_VENDOR_DIR . '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/symfony/process')
->in(WP_CLI_VENDOR_DIR . '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/justinrainbow/json-schema')
+ ->exclude('demo')
->exclude('nb/oxymel/OxymelTest.php')
->exclude('composer/spdx-licenses')
->exclude('composer/composer/src/Composer/Command')
@@ -235,6 +306,7 @@ function set_file_contents( $phar, $path, $content ) {
}
add_file( $phar, WP_CLI_VENDOR_DIR . '/rmccue/requests/library/Requests/Transport/cacert.pem' );
+set_file_contents( $phar, WP_CLI_ROOT . '/COMPOSER_VERSIONS', get_composer_versions( $current_version ) );
set_file_contents( $phar, WP_CLI_ROOT . '/VERSION', $current_version );
$phar_boot = str_replace( WP_CLI_BASE_PATH, '', WP_CLI_ROOT . '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/php/boot-phar.php' );
@@ -253,5 +325,5 @@ function set_file_contents( $phar, $path, $content ) {
chmod( DEST_PATH, 0755 ); // Make executable.
if ( ! BE_QUIET ) {
- echo "Generated " . DEST_PATH . "\n";
+ echo "Generated " . DEST_PATH . PHP_EOL;
}