diff --git a/.adr-dir b/.adr-dir new file mode 100644 index 00000000..da5cac6b --- /dev/null +++ b/.adr-dir @@ -0,0 +1 @@ +docs/architecture/decisions diff --git a/.github/dependabot.yml b/.github/dependabot.yml index 2e616059..76896a82 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -5,8 +5,3 @@ updates: directory: "/" schedule: interval: daily -- package-ecosystem: composer - directory: "/" - schedule: - interval: daily - open-pull-requests-limit: 0 diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 00000000..74c2b056 --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,26 @@ +name: Rust + +on: + push: + pull_request: + +env: + CARGO_TERM_COLOR: always + +jobs: + build: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - name: Build + run: | + rustup --version + ./script/test + - name: Cache dependencies + uses: actions/cache@v4 + with: + path: | + ~/.cargo/registry + ~/.cargo/git + target + key: ${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.lock') }} diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml deleted file mode 100644 index 634ae48b..00000000 --- a/.github/workflows/main.yml +++ /dev/null @@ -1,40 +0,0 @@ -name: Tests & Linting - -on: push - -jobs: - run: - runs-on: ubuntu-24.04 - strategy: - matrix: - php-versions: ['7.4', '8.0', '8.1', '8.2'] - fail-fast: false - name: PHP ${{ matrix.php-versions }} - steps: - - name: Checkout - uses: actions/checkout@v4 - - - name: Setup PHP - uses: shivammathur/setup-php@v2 - with: - php-version: ${{ matrix.php-versions }} - - - name: Get Composer Cache Directory - id: composer-cache - run: | - echo "::set-output name=dir::$(composer config cache-files-dir)" - - uses: actions/cache@v4 - with: - path: ${{ steps.composer-cache.outputs.dir }} - key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.lock') }} - restore-keys: | - ${{ runner.os }}-composer- - - - name: git config (required for PluginsTest) - run: git config --global user.email you@example.com && git config --global user.name you - - - name: Run lints and tests - run: ./script/test - - - name: Run Psalm for this specific PHP version - run: ./vendor/bin/psalm --php-version=${{ matrix.php-versions }} diff --git a/.gitignore b/.gitignore index 0b1abe85..4f518cb0 100644 --- a/.gitignore +++ b/.gitignore @@ -1,8 +1,5 @@ -/vendor -/tests/plugins-test-dir -/docker-images/.DS_Store -/docker-images/whippet-wordpress/.DS_Store -npm-debug.log -/.php_cs.cache -/.php-cs-fixer.cache -/.phpunit.result.cache + + +# Added by cargo + +/target diff --git a/.php-cs-fixer.php b/.php-cs-fixer.php deleted file mode 100644 index a797a9e4..00000000 --- a/.php-cs-fixer.php +++ /dev/null @@ -1,9 +0,0 @@ -exclude('generators') -->exclude('vendor') -->in(__DIR__); - -return \Dxw\PhpCsFixerConfig\Config::create() -->setFinder($finder); diff --git a/Brewfile b/Brewfile index dc5aa269..471b7a46 100644 --- a/Brewfile +++ b/Brewfile @@ -1,3 +1,2 @@ -brew "php@7.4" -brew "composer" +brew "rust" brew "shellcheck" diff --git a/CHANGELOG.md b/CHANGELOG.md index 305341e5..15347dbc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,9 +6,15 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## Unreleased +## Added +- Cargo tooling for Rust + ### Changed - Use current dxw Git URIs for documentation and tests +### Removed +- PHP version of Whippet + ## [v2.5.0] - 2024-07-24 ### Added diff --git a/Cargo.lock b/Cargo.lock new file mode 100644 index 00000000..9e4766f3 --- /dev/null +++ b/Cargo.lock @@ -0,0 +1,7 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 4 + +[[package]] +name = "whippet" +version = "3.0.0" diff --git a/Cargo.toml b/Cargo.toml new file mode 100644 index 00000000..5cf2c65c --- /dev/null +++ b/Cargo.toml @@ -0,0 +1,6 @@ +[package] +name = "whippet" +version = "3.0.0" +edition = "2024" + +[dependencies] diff --git a/README.md b/README.md index 2ba633e3..f12f0d9e 100644 --- a/README.md +++ b/README.md @@ -1,72 +1,7 @@ # Whippet -This project is a framework for building WordPress applications that eases deployment, plugin management and build steps. Whippet is part of dxw's work to build and host WordPress-based applications that conform more closely to 12-factor principles. - -Whippet has a few basic goals: - -1. Allowing proper build steps to take place, that automate build tasks both during development and deployment -2. Properly managing plugins and themes, allowing them to be version controlled and easily updated -3. Managing the creation of releases, including rollbacks -4. Automating the generation of commonly required objects like new applications and new themes - -Whippet can manage plugins and themes and releases. - -During development, whippet can be used in conjunction with [wpc](https://github.com/dxw/wpc). - -*Whippet is under development and should be considered alpha software. If you use it, we'd love to know what you think.* - -## Getting started - -You will need: - -* [PHP](https://www.php.net/) -* [Composer](https://getcomposer.org/) -* [git](https://git-scm.com/) - -### Install whippet - -#### Via homebrew (recommended) - -You can install Whippet via Homebrew by running: - -``` -brew install dxw/tap/whippet -``` - -#### From source - -Whippet implements the [scripts to rule them all](https://github.com/github/scripts-to-rule-them-all) -pattern. To install Whippet from source, clone this repository: - -```shell -$ git clone https://github.com/dxw/whippet.git -``` - -Then run the relevant script to setup your environment and install dependencies: - -```shell -./script/setup -``` - -You might also want to symlink whippet to somewhere in your path: - -```shell -sudo ln -s $PWD/bin/whippet /usr/local/bin/whippet -``` - -## Using Whippet - -The main things you can use Whippet to do are: - -* [Generating a Whippet application or theme](docs/generate.md) -* [Managing themes and plugins](docs/themesandplugins.md) -* [Deploying a Whippet application](docs/deploy.md) - -## Support - -For dxw developers who will encounter Whippet in a support context. - -See the [Support](docs/support.md) doc. +This is an experimental re-write of Whippet. If you are trying to do something +useful please use the `main` branch. ## Licence diff --git a/bin/whippet b/bin/whippet deleted file mode 100755 index 077df182..00000000 --- a/bin/whippet +++ /dev/null @@ -1,26 +0,0 @@ -#!/usr/bin/env php -register(); -$loader->addPrefix('Dxw\\Whippet', __DIR__.'/../src'); - -date_default_timezone_set("UTC"); - -define('WHIPPET_ROOT', dirname(dirname(__FILE__))); - -$whippet = new \Dxw\Whippet\Whippet(); -$whippet->start($argv); diff --git a/composer.json b/composer.json deleted file mode 100644 index b6b8b412..00000000 --- a/composer.json +++ /dev/null @@ -1,35 +0,0 @@ -{ - "name": "dxw/whippet", - "description": "", - "bin": ["bin/whippet"], - "scripts": { - "post-update-cmd": "vendor/bin/phar-install" - }, - "autoload": { - "psr-4": { - "Dxw\\Whippet\\": "src/" - } - }, - "config": { - "platform": { - "php":"7.4" - } - }, - "require": { - "php": "^7.4||^8.0", - "dxw/rubbishthorclone": "^1.0", - "aura/autoload": "^2.0", - "nikita2206/result": "^0.2.0", - "kevinlebrun/colors.php": "^1.0", - "guzzlehttp/guzzle": "^6.5.8" - }, - "require-dev": { - "phpunit/phpunit": "^9.0", - "mockery/mockery": "^1.1", - "dxw/phar-install": "^1.1", - "mikey179/vfsstream": "^1.6", - "dxw/php-cs-fixer-config": "^2.0", - "kahlan/kahlan": "^5.1", - "vimeo/psalm": "^5.15" - } -} diff --git a/composer.lock b/composer.lock deleted file mode 100644 index 612dd638..00000000 --- a/composer.lock +++ /dev/null @@ -1,5664 +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#installing-dependencies", - "This file is @generated automatically" - ], - "content-hash": "bf29d8b7a0135e28b9f5f2bb31ae2a22", - "packages": [ - { - "name": "aura/autoload", - "version": "2.0.4", - "source": { - "type": "git", - "url": "https://github.com/auraphp/Aura.Autoload.git", - "reference": "306a7f8d3cb58fb6f94bcff1dddf20c543f68668" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/auraphp/Aura.Autoload/zipball/306a7f8d3cb58fb6f94bcff1dddf20c543f68668", - "reference": "306a7f8d3cb58fb6f94bcff1dddf20c543f68668", - "shasum": "" - }, - "require": { - "php": ">=5.3.0" - }, - "type": "library", - "extra": { - "aura": { - "type": "library" - } - }, - "autoload": { - "psr-4": { - "Aura\\Autoload\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-2-Clause" - ], - "authors": [ - { - "name": "Aura.Autoload Contributors", - "homepage": "https://github.com/auraphp/Aura.Autoload/contributors" - } - ], - "description": "Provides a PSR-4 compliant autoloader implementation.", - "homepage": "https://github.com/auraphp/Aura.Autoload", - "keywords": [ - "PSR-4", - "SPL autoloader", - "autoload", - "autoloader", - "class loader" - ], - "support": { - "issues": "https://github.com/auraphp/Aura.Autoload/issues", - "source": "https://github.com/auraphp/Aura.Autoload/tree/2.x" - }, - "time": "2016-10-03T19:36:19+00:00" - }, - { - "name": "dxw/optionparser", - "version": "v1.0.0", - "source": { - "type": "git", - "url": "https://github.com/dxw/optionparser.git", - "reference": "09dcb3bf0271c1b10b5540f50cdf5c18c8133886" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/dxw/optionparser/zipball/09dcb3bf0271c1b10b5540f50cdf5c18c8133886", - "reference": "09dcb3bf0271c1b10b5540f50cdf5c18c8133886", - "shasum": "" - }, - "type": "library", - "autoload": { - "files": [ - "lib/OptionParser.php" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "support": { - "source": "https://github.com/dxw/optionparser/tree/v1.0.0" - }, - "abandoned": true, - "time": "2020-02-14T13:48:18+00:00" - }, - { - "name": "dxw/rubbishthorclone", - "version": "v1.0.2", - "source": { - "type": "git", - "url": "https://github.com/dxw/RubbishThorClone.git", - "reference": "af23b936583bd93c1741aa274339ea48b74fabf9" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/dxw/RubbishThorClone/zipball/af23b936583bd93c1741aa274339ea48b74fabf9", - "reference": "af23b936583bd93c1741aa274339ea48b74fabf9", - "shasum": "" - }, - "require": { - "dxw/optionparser": "^1.0", - "pear/console_table": "*" - }, - "require-dev": { - "vimeo/psalm": "^5.14" - }, - "type": "library", - "autoload": { - "files": [ - "rubbish_thor_clone.class.php" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "support": { - "issues": "https://github.com/dxw/RubbishThorClone/issues", - "source": "https://github.com/dxw/RubbishThorClone/tree/v1.0.2" - }, - "time": "2023-08-17T08:53:56+00:00" - }, - { - "name": "guzzlehttp/guzzle", - "version": "6.5.8", - "source": { - "type": "git", - "url": "https://github.com/guzzle/guzzle.git", - "reference": "a52f0440530b54fa079ce76e8c5d196a42cad981" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/guzzle/guzzle/zipball/a52f0440530b54fa079ce76e8c5d196a42cad981", - "reference": "a52f0440530b54fa079ce76e8c5d196a42cad981", - "shasum": "" - }, - "require": { - "ext-json": "*", - "guzzlehttp/promises": "^1.0", - "guzzlehttp/psr7": "^1.9", - "php": ">=5.5", - "symfony/polyfill-intl-idn": "^1.17" - }, - "require-dev": { - "ext-curl": "*", - "phpunit/phpunit": "^4.8.35 || ^5.7 || ^6.4 || ^7.0", - "psr/log": "^1.1" - }, - "suggest": { - "psr/log": "Required for using the Log middleware" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "6.5-dev" - } - }, - "autoload": { - "files": [ - "src/functions_include.php" - ], - "psr-4": { - "GuzzleHttp\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Graham Campbell", - "email": "hello@gjcampbell.co.uk", - "homepage": "https://github.com/GrahamCampbell" - }, - { - "name": "Michael Dowling", - "email": "mtdowling@gmail.com", - "homepage": "https://github.com/mtdowling" - }, - { - "name": "Jeremy Lindblom", - "email": "jeremeamia@gmail.com", - "homepage": "https://github.com/jeremeamia" - }, - { - "name": "George Mponos", - "email": "gmponos@gmail.com", - "homepage": "https://github.com/gmponos" - }, - { - "name": "Tobias Nyholm", - "email": "tobias.nyholm@gmail.com", - "homepage": "https://github.com/Nyholm" - }, - { - "name": "Márk Sági-Kazár", - "email": "mark.sagikazar@gmail.com", - "homepage": "https://github.com/sagikazarmark" - }, - { - "name": "Tobias Schultze", - "email": "webmaster@tubo-world.de", - "homepage": "https://github.com/Tobion" - } - ], - "description": "Guzzle is a PHP HTTP client library", - "homepage": "http://guzzlephp.org/", - "keywords": [ - "client", - "curl", - "framework", - "http", - "http client", - "rest", - "web service" - ], - "support": { - "issues": "https://github.com/guzzle/guzzle/issues", - "source": "https://github.com/guzzle/guzzle/tree/6.5.8" - }, - "funding": [ - { - "url": "https://github.com/GrahamCampbell", - "type": "github" - }, - { - "url": "https://github.com/Nyholm", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/guzzlehttp/guzzle", - "type": "tidelift" - } - ], - "time": "2022-06-20T22:16:07+00:00" - }, - { - "name": "guzzlehttp/promises", - "version": "1.5.3", - "source": { - "type": "git", - "url": "https://github.com/guzzle/promises.git", - "reference": "67ab6e18aaa14d753cc148911d273f6e6cb6721e" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/guzzle/promises/zipball/67ab6e18aaa14d753cc148911d273f6e6cb6721e", - "reference": "67ab6e18aaa14d753cc148911d273f6e6cb6721e", - "shasum": "" - }, - "require": { - "php": ">=5.5" - }, - "require-dev": { - "symfony/phpunit-bridge": "^4.4 || ^5.1" - }, - "type": "library", - "autoload": { - "files": [ - "src/functions_include.php" - ], - "psr-4": { - "GuzzleHttp\\Promise\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Graham Campbell", - "email": "hello@gjcampbell.co.uk", - "homepage": "https://github.com/GrahamCampbell" - }, - { - "name": "Michael Dowling", - "email": "mtdowling@gmail.com", - "homepage": "https://github.com/mtdowling" - }, - { - "name": "Tobias Nyholm", - "email": "tobias.nyholm@gmail.com", - "homepage": "https://github.com/Nyholm" - }, - { - "name": "Tobias Schultze", - "email": "webmaster@tubo-world.de", - "homepage": "https://github.com/Tobion" - } - ], - "description": "Guzzle promises library", - "keywords": [ - "promise" - ], - "support": { - "issues": "https://github.com/guzzle/promises/issues", - "source": "https://github.com/guzzle/promises/tree/1.5.3" - }, - "funding": [ - { - "url": "https://github.com/GrahamCampbell", - "type": "github" - }, - { - "url": "https://github.com/Nyholm", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/guzzlehttp/promises", - "type": "tidelift" - } - ], - "time": "2023-05-21T12:31:43+00:00" - }, - { - "name": "guzzlehttp/psr7", - "version": "1.9.1", - "source": { - "type": "git", - "url": "https://github.com/guzzle/psr7.git", - "reference": "e4490cabc77465aaee90b20cfc9a770f8c04be6b" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/guzzle/psr7/zipball/e4490cabc77465aaee90b20cfc9a770f8c04be6b", - "reference": "e4490cabc77465aaee90b20cfc9a770f8c04be6b", - "shasum": "" - }, - "require": { - "php": ">=5.4.0", - "psr/http-message": "~1.0", - "ralouphie/getallheaders": "^2.0.5 || ^3.0.0" - }, - "provide": { - "psr/http-message-implementation": "1.0" - }, - "require-dev": { - "ext-zlib": "*", - "phpunit/phpunit": "~4.8.36 || ^5.7.27 || ^6.5.14 || ^7.5.20 || ^8.5.8 || ^9.3.10" - }, - "suggest": { - "laminas/laminas-httphandlerrunner": "Emit PSR-7 responses" - }, - "type": "library", - "autoload": { - "files": [ - "src/functions_include.php" - ], - "psr-4": { - "GuzzleHttp\\Psr7\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Graham Campbell", - "email": "hello@gjcampbell.co.uk", - "homepage": "https://github.com/GrahamCampbell" - }, - { - "name": "Michael Dowling", - "email": "mtdowling@gmail.com", - "homepage": "https://github.com/mtdowling" - }, - { - "name": "George Mponos", - "email": "gmponos@gmail.com", - "homepage": "https://github.com/gmponos" - }, - { - "name": "Tobias Nyholm", - "email": "tobias.nyholm@gmail.com", - "homepage": "https://github.com/Nyholm" - }, - { - "name": "Márk Sági-Kazár", - "email": "mark.sagikazar@gmail.com", - "homepage": "https://github.com/sagikazarmark" - }, - { - "name": "Tobias Schultze", - "email": "webmaster@tubo-world.de", - "homepage": "https://github.com/Tobion" - } - ], - "description": "PSR-7 message implementation that also provides common utility methods", - "keywords": [ - "http", - "message", - "psr-7", - "request", - "response", - "stream", - "uri", - "url" - ], - "support": { - "issues": "https://github.com/guzzle/psr7/issues", - "source": "https://github.com/guzzle/psr7/tree/1.9.1" - }, - "funding": [ - { - "url": "https://github.com/GrahamCampbell", - "type": "github" - }, - { - "url": "https://github.com/Nyholm", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/guzzlehttp/psr7", - "type": "tidelift" - } - ], - "time": "2023-04-17T16:00:37+00:00" - }, - { - "name": "kevinlebrun/colors.php", - "version": "1.0.3", - "source": { - "type": "git", - "url": "https://github.com/kevinlebrun/colors.php.git", - "reference": "cdda5eee41314b87cd5a8bb91b1ffc7c0210e673" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/kevinlebrun/colors.php/zipball/cdda5eee41314b87cd5a8bb91b1ffc7c0210e673", - "reference": "cdda5eee41314b87cd5a8bb91b1ffc7c0210e673", - "shasum": "" - }, - "require": { - "php": ">=5.3.0" - }, - "require-dev": { - "phpunit/phpunit": "3.7.*", - "satooshi/php-coveralls": "1.0.*", - "squizlabs/php_codesniffer": "1.*" - }, - "type": "library", - "autoload": { - "psr-0": { - "Colors": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Kevin Le Brun", - "email": "lebrun.k@gmail.com", - "homepage": "http://kevinlebrun.fr", - "role": "developer" - } - ], - "description": "Colors for PHP CLI scripts", - "homepage": "https://github.com/kevinlebrun/colors.php", - "keywords": [ - "cli", - "color", - "colors", - "console", - "shell" - ], - "support": { - "issues": "https://github.com/kevinlebrun/colors.php/issues", - "source": "https://github.com/kevinlebrun/colors.php/tree/master" - }, - "time": "2018-05-30T08:34:23+00:00" - }, - { - "name": "nikita2206/result", - "version": "0.2", - "source": { - "type": "git", - "url": "https://github.com/nikita2206/result.git", - "reference": "7b08cb5a2ecd79843d34aec3902b0ea973a92473" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/nikita2206/result/zipball/7b08cb5a2ecd79843d34aec3902b0ea973a92473", - "reference": "7b08cb5a2ecd79843d34aec3902b0ea973a92473", - "shasum": "" - }, - "require": { - "php": ">=5.5" - }, - "require-dev": { - "phpunit/phpunit": "~4" - }, - "type": "library", - "autoload": { - "psr-4": { - "Result\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Nikita Nefedov", - "email": "inefedor@gmail.com" - } - ], - "description": "Result data type (just like in Rust)", - "support": { - "issues": "https://github.com/nikita2206/result/issues", - "source": "https://github.com/nikita2206/result/tree/master" - }, - "time": "2016-03-25T16:02:11+00:00" - }, - { - "name": "pear/console_table", - "version": "v1.3.1", - "source": { - "type": "git", - "url": "https://github.com/pear/Console_Table.git", - "reference": "1930c11897ca61fd24b95f2f785e99e0f36dcdea" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/pear/Console_Table/zipball/1930c11897ca61fd24b95f2f785e99e0f36dcdea", - "reference": "1930c11897ca61fd24b95f2f785e99e0f36dcdea", - "shasum": "" - }, - "require": { - "php": ">=5.2.0" - }, - "suggest": { - "pear/Console_Color2": ">=0.1.2" - }, - "type": "library", - "autoload": { - "classmap": [ - "Table.php" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-2-Clause" - ], - "authors": [ - { - "name": "Jan Schneider", - "homepage": "http://pear.php.net/user/yunosh" - }, - { - "name": "Tal Peer", - "homepage": "http://pear.php.net/user/tal" - }, - { - "name": "Xavier Noguer", - "homepage": "http://pear.php.net/user/xnoguer" - }, - { - "name": "Richard Heyes", - "homepage": "http://pear.php.net/user/richard" - } - ], - "description": "Library that makes it easy to build console style tables.", - "homepage": "http://pear.php.net/package/Console_Table/", - "keywords": [ - "console" - ], - "support": { - "issues": "http://pear.php.net/bugs/search.php?cmd=display&package_name[]=Console_Table", - "source": "https://github.com/pear/Console_Table" - }, - "time": "2018-01-25T20:47:17+00:00" - }, - { - "name": "psr/http-message", - "version": "1.1", - "source": { - "type": "git", - "url": "https://github.com/php-fig/http-message.git", - "reference": "cb6ce4845ce34a8ad9e68117c10ee90a29919eba" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/php-fig/http-message/zipball/cb6ce4845ce34a8ad9e68117c10ee90a29919eba", - "reference": "cb6ce4845ce34a8ad9e68117c10ee90a29919eba", - "shasum": "" - }, - "require": { - "php": "^7.2 || ^8.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.1.x-dev" - } - }, - "autoload": { - "psr-4": { - "Psr\\Http\\Message\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "PHP-FIG", - "homepage": "http://www.php-fig.org/" - } - ], - "description": "Common interface for HTTP messages", - "homepage": "https://github.com/php-fig/http-message", - "keywords": [ - "http", - "http-message", - "psr", - "psr-7", - "request", - "response" - ], - "support": { - "source": "https://github.com/php-fig/http-message/tree/1.1" - }, - "time": "2023-04-04T09:50:52+00:00" - }, - { - "name": "ralouphie/getallheaders", - "version": "3.0.3", - "source": { - "type": "git", - "url": "https://github.com/ralouphie/getallheaders.git", - "reference": "120b605dfeb996808c31b6477290a714d356e822" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/ralouphie/getallheaders/zipball/120b605dfeb996808c31b6477290a714d356e822", - "reference": "120b605dfeb996808c31b6477290a714d356e822", - "shasum": "" - }, - "require": { - "php": ">=5.6" - }, - "require-dev": { - "php-coveralls/php-coveralls": "^2.1", - "phpunit/phpunit": "^5 || ^6.5" - }, - "type": "library", - "autoload": { - "files": [ - "src/getallheaders.php" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Ralph Khattar", - "email": "ralph.khattar@gmail.com" - } - ], - "description": "A polyfill for getallheaders.", - "support": { - "issues": "https://github.com/ralouphie/getallheaders/issues", - "source": "https://github.com/ralouphie/getallheaders/tree/develop" - }, - "time": "2019-03-08T08:55:37+00:00" - }, - { - "name": "symfony/polyfill-intl-idn", - "version": "v1.28.0", - "source": { - "type": "git", - "url": "https://github.com/symfony/polyfill-intl-idn.git", - "reference": "ecaafce9f77234a6a449d29e49267ba10499116d" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-intl-idn/zipball/ecaafce9f77234a6a449d29e49267ba10499116d", - "reference": "ecaafce9f77234a6a449d29e49267ba10499116d", - "shasum": "" - }, - "require": { - "php": ">=7.1", - "symfony/polyfill-intl-normalizer": "^1.10", - "symfony/polyfill-php72": "^1.10" - }, - "suggest": { - "ext-intl": "For best performance" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "1.28-dev" - }, - "thanks": { - "name": "symfony/polyfill", - "url": "https://github.com/symfony/polyfill" - } - }, - "autoload": { - "files": [ - "bootstrap.php" - ], - "psr-4": { - "Symfony\\Polyfill\\Intl\\Idn\\": "" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Laurent Bassin", - "email": "laurent@bassin.info" - }, - { - "name": "Trevor Rowbotham", - "email": "trevor.rowbotham@pm.me" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Symfony polyfill for intl's idn_to_ascii and idn_to_utf8 functions", - "homepage": "https://symfony.com", - "keywords": [ - "compatibility", - "idn", - "intl", - "polyfill", - "portable", - "shim" - ], - "support": { - "source": "https://github.com/symfony/polyfill-intl-idn/tree/v1.28.0" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2023-01-26T09:30:37+00:00" - }, - { - "name": "symfony/polyfill-intl-normalizer", - "version": "v1.28.0", - "source": { - "type": "git", - "url": "https://github.com/symfony/polyfill-intl-normalizer.git", - "reference": "8c4ad05dd0120b6a53c1ca374dca2ad0a1c4ed92" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-intl-normalizer/zipball/8c4ad05dd0120b6a53c1ca374dca2ad0a1c4ed92", - "reference": "8c4ad05dd0120b6a53c1ca374dca2ad0a1c4ed92", - "shasum": "" - }, - "require": { - "php": ">=7.1" - }, - "suggest": { - "ext-intl": "For best performance" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "1.28-dev" - }, - "thanks": { - "name": "symfony/polyfill", - "url": "https://github.com/symfony/polyfill" - } - }, - "autoload": { - "files": [ - "bootstrap.php" - ], - "psr-4": { - "Symfony\\Polyfill\\Intl\\Normalizer\\": "" - }, - "classmap": [ - "Resources/stubs" - ] - }, - "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 intl's Normalizer class and related functions", - "homepage": "https://symfony.com", - "keywords": [ - "compatibility", - "intl", - "normalizer", - "polyfill", - "portable", - "shim" - ], - "support": { - "source": "https://github.com/symfony/polyfill-intl-normalizer/tree/v1.28.0" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2023-01-26T09:26:14+00:00" - }, - { - "name": "symfony/polyfill-php72", - "version": "v1.28.0", - "source": { - "type": "git", - "url": "https://github.com/symfony/polyfill-php72.git", - "reference": "70f4aebd92afca2f865444d30a4d2151c13c3179" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-php72/zipball/70f4aebd92afca2f865444d30a4d2151c13c3179", - "reference": "70f4aebd92afca2f865444d30a4d2151c13c3179", - "shasum": "" - }, - "require": { - "php": ">=7.1" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "1.28-dev" - }, - "thanks": { - "name": "symfony/polyfill", - "url": "https://github.com/symfony/polyfill" - } - }, - "autoload": { - "files": [ - "bootstrap.php" - ], - "psr-4": { - "Symfony\\Polyfill\\Php72\\": "" - } - }, - "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 backporting some PHP 7.2+ features to lower PHP versions", - "homepage": "https://symfony.com", - "keywords": [ - "compatibility", - "polyfill", - "portable", - "shim" - ], - "support": { - "source": "https://github.com/symfony/polyfill-php72/tree/v1.28.0" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2023-01-26T09:26:14+00:00" - } - ], - "packages-dev": [ - { - "name": "amphp/amp", - "version": "v2.6.2", - "source": { - "type": "git", - "url": "https://github.com/amphp/amp.git", - "reference": "9d5100cebffa729aaffecd3ad25dc5aeea4f13bb" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/amphp/amp/zipball/9d5100cebffa729aaffecd3ad25dc5aeea4f13bb", - "reference": "9d5100cebffa729aaffecd3ad25dc5aeea4f13bb", - "shasum": "" - }, - "require": { - "php": ">=7.1" - }, - "require-dev": { - "amphp/php-cs-fixer-config": "dev-master", - "amphp/phpunit-util": "^1", - "ext-json": "*", - "jetbrains/phpstorm-stubs": "^2019.3", - "phpunit/phpunit": "^7 | ^8 | ^9", - "psalm/phar": "^3.11@dev", - "react/promise": "^2" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "2.x-dev" - } - }, - "autoload": { - "files": [ - "lib/functions.php", - "lib/Internal/functions.php" - ], - "psr-4": { - "Amp\\": "lib" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Daniel Lowrey", - "email": "rdlowrey@php.net" - }, - { - "name": "Aaron Piotrowski", - "email": "aaron@trowski.com" - }, - { - "name": "Bob Weinand", - "email": "bobwei9@hotmail.com" - }, - { - "name": "Niklas Keller", - "email": "me@kelunik.com" - } - ], - "description": "A non-blocking concurrency framework for PHP applications.", - "homepage": "https://amphp.org/amp", - "keywords": [ - "async", - "asynchronous", - "awaitable", - "concurrency", - "event", - "event-loop", - "future", - "non-blocking", - "promise" - ], - "support": { - "irc": "irc://irc.freenode.org/amphp", - "issues": "https://github.com/amphp/amp/issues", - "source": "https://github.com/amphp/amp/tree/v2.6.2" - }, - "funding": [ - { - "url": "https://github.com/amphp", - "type": "github" - } - ], - "time": "2022-02-20T17:52:18+00:00" - }, - { - "name": "amphp/byte-stream", - "version": "v1.8.1", - "source": { - "type": "git", - "url": "https://github.com/amphp/byte-stream.git", - "reference": "acbd8002b3536485c997c4e019206b3f10ca15bd" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/amphp/byte-stream/zipball/acbd8002b3536485c997c4e019206b3f10ca15bd", - "reference": "acbd8002b3536485c997c4e019206b3f10ca15bd", - "shasum": "" - }, - "require": { - "amphp/amp": "^2", - "php": ">=7.1" - }, - "require-dev": { - "amphp/php-cs-fixer-config": "dev-master", - "amphp/phpunit-util": "^1.4", - "friendsofphp/php-cs-fixer": "^2.3", - "jetbrains/phpstorm-stubs": "^2019.3", - "phpunit/phpunit": "^6 || ^7 || ^8", - "psalm/phar": "^3.11.4" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.x-dev" - } - }, - "autoload": { - "files": [ - "lib/functions.php" - ], - "psr-4": { - "Amp\\ByteStream\\": "lib" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Aaron Piotrowski", - "email": "aaron@trowski.com" - }, - { - "name": "Niklas Keller", - "email": "me@kelunik.com" - } - ], - "description": "A stream abstraction to make working with non-blocking I/O simple.", - "homepage": "http://amphp.org/byte-stream", - "keywords": [ - "amp", - "amphp", - "async", - "io", - "non-blocking", - "stream" - ], - "support": { - "irc": "irc://irc.freenode.org/amphp", - "issues": "https://github.com/amphp/byte-stream/issues", - "source": "https://github.com/amphp/byte-stream/tree/v1.8.1" - }, - "funding": [ - { - "url": "https://github.com/amphp", - "type": "github" - } - ], - "time": "2021-03-30T17:13:30+00:00" - }, - { - "name": "composer/pcre", - "version": "3.1.0", - "source": { - "type": "git", - "url": "https://github.com/composer/pcre.git", - "reference": "4bff79ddd77851fe3cdd11616ed3f92841ba5bd2" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/composer/pcre/zipball/4bff79ddd77851fe3cdd11616ed3f92841ba5bd2", - "reference": "4bff79ddd77851fe3cdd11616ed3f92841ba5bd2", - "shasum": "" - }, - "require": { - "php": "^7.4 || ^8.0" - }, - "require-dev": { - "phpstan/phpstan": "^1.3", - "phpstan/phpstan-strict-rules": "^1.1", - "symfony/phpunit-bridge": "^5" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "3.x-dev" - } - }, - "autoload": { - "psr-4": { - "Composer\\Pcre\\": "src" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Jordi Boggiano", - "email": "j.boggiano@seld.be", - "homepage": "http://seld.be" - } - ], - "description": "PCRE wrapping library that offers type-safe preg_* replacements.", - "keywords": [ - "PCRE", - "preg", - "regex", - "regular expression" - ], - "support": { - "issues": "https://github.com/composer/pcre/issues", - "source": "https://github.com/composer/pcre/tree/3.1.0" - }, - "funding": [ - { - "url": "https://packagist.com", - "type": "custom" - }, - { - "url": "https://github.com/composer", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/composer/composer", - "type": "tidelift" - } - ], - "time": "2022-11-17T09:50:14+00:00" - }, - { - "name": "composer/semver", - "version": "3.4.0", - "source": { - "type": "git", - "url": "https://github.com/composer/semver.git", - "reference": "35e8d0af4486141bc745f23a29cc2091eb624a32" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/composer/semver/zipball/35e8d0af4486141bc745f23a29cc2091eb624a32", - "reference": "35e8d0af4486141bc745f23a29cc2091eb624a32", - "shasum": "" - }, - "require": { - "php": "^5.3.2 || ^7.0 || ^8.0" - }, - "require-dev": { - "phpstan/phpstan": "^1.4", - "symfony/phpunit-bridge": "^4.2 || ^5" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "3.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" - ], - "support": { - "irc": "ircs://irc.libera.chat:6697/composer", - "issues": "https://github.com/composer/semver/issues", - "source": "https://github.com/composer/semver/tree/3.4.0" - }, - "funding": [ - { - "url": "https://packagist.com", - "type": "custom" - }, - { - "url": "https://github.com/composer", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/composer/composer", - "type": "tidelift" - } - ], - "time": "2023-08-31T09:50:34+00:00" - }, - { - "name": "composer/xdebug-handler", - "version": "3.0.3", - "source": { - "type": "git", - "url": "https://github.com/composer/xdebug-handler.git", - "reference": "ced299686f41dce890debac69273b47ffe98a40c" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/composer/xdebug-handler/zipball/ced299686f41dce890debac69273b47ffe98a40c", - "reference": "ced299686f41dce890debac69273b47ffe98a40c", - "shasum": "" - }, - "require": { - "composer/pcre": "^1 || ^2 || ^3", - "php": "^7.2.5 || ^8.0", - "psr/log": "^1 || ^2 || ^3" - }, - "require-dev": { - "phpstan/phpstan": "^1.0", - "phpstan/phpstan-strict-rules": "^1.1", - "symfony/phpunit-bridge": "^6.0" - }, - "type": "library", - "autoload": { - "psr-4": { - "Composer\\XdebugHandler\\": "src" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "John Stevenson", - "email": "john-stevenson@blueyonder.co.uk" - } - ], - "description": "Restarts a process without Xdebug.", - "keywords": [ - "Xdebug", - "performance" - ], - "support": { - "irc": "irc://irc.freenode.org/composer", - "issues": "https://github.com/composer/xdebug-handler/issues", - "source": "https://github.com/composer/xdebug-handler/tree/3.0.3" - }, - "funding": [ - { - "url": "https://packagist.com", - "type": "custom" - }, - { - "url": "https://github.com/composer", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/composer/composer", - "type": "tidelift" - } - ], - "time": "2022-02-25T21:32:43+00:00" - }, - { - "name": "dnoegel/php-xdg-base-dir", - "version": "v0.1.1", - "source": { - "type": "git", - "url": "https://github.com/dnoegel/php-xdg-base-dir.git", - "reference": "8f8a6e48c5ecb0f991c2fdcf5f154a47d85f9ffd" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/dnoegel/php-xdg-base-dir/zipball/8f8a6e48c5ecb0f991c2fdcf5f154a47d85f9ffd", - "reference": "8f8a6e48c5ecb0f991c2fdcf5f154a47d85f9ffd", - "shasum": "" - }, - "require": { - "php": ">=5.3.2" - }, - "require-dev": { - "phpunit/phpunit": "~7.0|~6.0|~5.0|~4.8.35" - }, - "type": "library", - "autoload": { - "psr-4": { - "XdgBaseDir\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "description": "implementation of xdg base directory specification for php", - "support": { - "issues": "https://github.com/dnoegel/php-xdg-base-dir/issues", - "source": "https://github.com/dnoegel/php-xdg-base-dir/tree/v0.1.1" - }, - "time": "2019-12-04T15:06:13+00:00" - }, - { - "name": "doctrine/deprecations", - "version": "1.1.2", - "source": { - "type": "git", - "url": "https://github.com/doctrine/deprecations.git", - "reference": "4f2d4f2836e7ec4e7a8625e75c6aa916004db931" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/doctrine/deprecations/zipball/4f2d4f2836e7ec4e7a8625e75c6aa916004db931", - "reference": "4f2d4f2836e7ec4e7a8625e75c6aa916004db931", - "shasum": "" - }, - "require": { - "php": "^7.1 || ^8.0" - }, - "require-dev": { - "doctrine/coding-standard": "^9", - "phpstan/phpstan": "1.4.10 || 1.10.15", - "phpstan/phpstan-phpunit": "^1.0", - "phpunit/phpunit": "^7.5 || ^8.5 || ^9.5", - "psalm/plugin-phpunit": "0.18.4", - "psr/log": "^1 || ^2 || ^3", - "vimeo/psalm": "4.30.0 || 5.12.0" - }, - "suggest": { - "psr/log": "Allows logging deprecations via PSR-3 logger implementation" - }, - "type": "library", - "autoload": { - "psr-4": { - "Doctrine\\Deprecations\\": "lib/Doctrine/Deprecations" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "description": "A small layer on top of trigger_error(E_USER_DEPRECATED) or PSR-3 logging with options to disable all deprecations or selectively for packages.", - "homepage": "https://www.doctrine-project.org/", - "support": { - "issues": "https://github.com/doctrine/deprecations/issues", - "source": "https://github.com/doctrine/deprecations/tree/1.1.2" - }, - "time": "2023-09-27T20:04:15+00:00" - }, - { - "name": "doctrine/instantiator", - "version": "1.5.0", - "source": { - "type": "git", - "url": "https://github.com/doctrine/instantiator.git", - "reference": "0a0fa9780f5d4e507415a065172d26a98d02047b" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/doctrine/instantiator/zipball/0a0fa9780f5d4e507415a065172d26a98d02047b", - "reference": "0a0fa9780f5d4e507415a065172d26a98d02047b", - "shasum": "" - }, - "require": { - "php": "^7.1 || ^8.0" - }, - "require-dev": { - "doctrine/coding-standard": "^9 || ^11", - "ext-pdo": "*", - "ext-phar": "*", - "phpbench/phpbench": "^0.16 || ^1", - "phpstan/phpstan": "^1.4", - "phpstan/phpstan-phpunit": "^1", - "phpunit/phpunit": "^7.5 || ^8.5 || ^9.5", - "vimeo/psalm": "^4.30 || ^5.4" - }, - "type": "library", - "autoload": { - "psr-4": { - "Doctrine\\Instantiator\\": "src/Doctrine/Instantiator/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Marco Pivetta", - "email": "ocramius@gmail.com", - "homepage": "https://ocramius.github.io/" - } - ], - "description": "A small, lightweight utility to instantiate objects in PHP without invoking their constructors", - "homepage": "https://www.doctrine-project.org/projects/instantiator.html", - "keywords": [ - "constructor", - "instantiate" - ], - "support": { - "issues": "https://github.com/doctrine/instantiator/issues", - "source": "https://github.com/doctrine/instantiator/tree/1.5.0" - }, - "funding": [ - { - "url": "https://www.doctrine-project.org/sponsorship.html", - "type": "custom" - }, - { - "url": "https://www.patreon.com/phpdoctrine", - "type": "patreon" - }, - { - "url": "https://tidelift.com/funding/github/packagist/doctrine%2Finstantiator", - "type": "tidelift" - } - ], - "time": "2022-12-30T00:15:36+00:00" - }, - { - "name": "dxw/phar-install", - "version": "v1.1.2", - "source": { - "type": "git", - "url": "https://github.com/dxw/phar-install.git", - "reference": "36eb78be91d433546bc90194db6f4de754a542de" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/dxw/phar-install/zipball/36eb78be91d433546bc90194db6f4de754a542de", - "reference": "36eb78be91d433546bc90194db6f4de754a542de", - "shasum": "" - }, - "bin": [ - "bin/phar-install" - ], - "type": "library", - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Mallory Adams", - "email": "mallory@dxw.com", - "homepage": "https://www.dxw.com" - } - ], - "homepage": "https://github.com/dxw/phar-install", - "support": { - "issues": "https://github.com/dxw/phar-install/issues", - "source": "https://github.com/dxw/phar-install/tree/master" - }, - "time": "2020-04-06T09:47:56+00:00" - }, - { - "name": "dxw/php-cs-fixer-config", - "version": "v2.1.1", - "source": { - "type": "git", - "url": "https://github.com/dxw/php-cs-fixer-config.git", - "reference": "690a251beb6a3080a2de5adc749675a99e22d9fd" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/dxw/php-cs-fixer-config/zipball/690a251beb6a3080a2de5adc749675a99e22d9fd", - "reference": "690a251beb6a3080a2de5adc749675a99e22d9fd", - "shasum": "" - }, - "require": { - "friendsofphp/php-cs-fixer": "^3.2", - "php": "^7.4||^8.1" - }, - "require-dev": { - "phpunit/phpunit": "^9.0", - "vimeo/psalm": "^5.15" - }, - "type": "library", - "autoload": { - "psr-4": { - "Dxw\\PhpCsFixerConfig\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "support": { - "issues": "https://github.com/dxw/php-cs-fixer-config/issues", - "source": "https://github.com/dxw/php-cs-fixer-config/tree/v2.1.1" - }, - "time": "2023-09-13T12:53:23+00:00" - }, - { - "name": "felixfbecker/advanced-json-rpc", - "version": "v3.2.1", - "source": { - "type": "git", - "url": "https://github.com/felixfbecker/php-advanced-json-rpc.git", - "reference": "b5f37dbff9a8ad360ca341f3240dc1c168b45447" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/felixfbecker/php-advanced-json-rpc/zipball/b5f37dbff9a8ad360ca341f3240dc1c168b45447", - "reference": "b5f37dbff9a8ad360ca341f3240dc1c168b45447", - "shasum": "" - }, - "require": { - "netresearch/jsonmapper": "^1.0 || ^2.0 || ^3.0 || ^4.0", - "php": "^7.1 || ^8.0", - "phpdocumentor/reflection-docblock": "^4.3.4 || ^5.0.0" - }, - "require-dev": { - "phpunit/phpunit": "^7.0 || ^8.0" - }, - "type": "library", - "autoload": { - "psr-4": { - "AdvancedJsonRpc\\": "lib/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "ISC" - ], - "authors": [ - { - "name": "Felix Becker", - "email": "felix.b@outlook.com" - } - ], - "description": "A more advanced JSONRPC implementation", - "support": { - "issues": "https://github.com/felixfbecker/php-advanced-json-rpc/issues", - "source": "https://github.com/felixfbecker/php-advanced-json-rpc/tree/v3.2.1" - }, - "time": "2021-06-11T22:34:44+00:00" - }, - { - "name": "felixfbecker/language-server-protocol", - "version": "v1.5.2", - "source": { - "type": "git", - "url": "https://github.com/felixfbecker/php-language-server-protocol.git", - "reference": "6e82196ffd7c62f7794d778ca52b69feec9f2842" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/felixfbecker/php-language-server-protocol/zipball/6e82196ffd7c62f7794d778ca52b69feec9f2842", - "reference": "6e82196ffd7c62f7794d778ca52b69feec9f2842", - "shasum": "" - }, - "require": { - "php": ">=7.1" - }, - "require-dev": { - "phpstan/phpstan": "*", - "squizlabs/php_codesniffer": "^3.1", - "vimeo/psalm": "^4.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.x-dev" - } - }, - "autoload": { - "psr-4": { - "LanguageServerProtocol\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "ISC" - ], - "authors": [ - { - "name": "Felix Becker", - "email": "felix.b@outlook.com" - } - ], - "description": "PHP classes for the Language Server Protocol", - "keywords": [ - "language", - "microsoft", - "php", - "server" - ], - "support": { - "issues": "https://github.com/felixfbecker/php-language-server-protocol/issues", - "source": "https://github.com/felixfbecker/php-language-server-protocol/tree/v1.5.2" - }, - "time": "2022-03-02T22:36:06+00:00" - }, - { - "name": "fidry/cpu-core-counter", - "version": "0.5.1", - "source": { - "type": "git", - "url": "https://github.com/theofidry/cpu-core-counter.git", - "reference": "b58e5a3933e541dc286cc91fc4f3898bbc6f1623" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/theofidry/cpu-core-counter/zipball/b58e5a3933e541dc286cc91fc4f3898bbc6f1623", - "reference": "b58e5a3933e541dc286cc91fc4f3898bbc6f1623", - "shasum": "" - }, - "require": { - "php": "^7.2 || ^8.0" - }, - "require-dev": { - "fidry/makefile": "^0.2.0", - "phpstan/extension-installer": "^1.2.0", - "phpstan/phpstan": "^1.9.2", - "phpstan/phpstan-deprecation-rules": "^1.0.0", - "phpstan/phpstan-phpunit": "^1.2.2", - "phpstan/phpstan-strict-rules": "^1.4.4", - "phpunit/phpunit": "^9.5.26 || ^8.5.31", - "theofidry/php-cs-fixer-config": "^1.0", - "webmozarts/strict-phpunit": "^7.5" - }, - "type": "library", - "autoload": { - "psr-4": { - "Fidry\\CpuCoreCounter\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Théo FIDRY", - "email": "theo.fidry@gmail.com" - } - ], - "description": "Tiny utility to get the number of CPU cores.", - "keywords": [ - "CPU", - "core" - ], - "support": { - "issues": "https://github.com/theofidry/cpu-core-counter/issues", - "source": "https://github.com/theofidry/cpu-core-counter/tree/0.5.1" - }, - "funding": [ - { - "url": "https://github.com/theofidry", - "type": "github" - } - ], - "time": "2022-12-24T12:35:10+00:00" - }, - { - "name": "friendsofphp/php-cs-fixer", - "version": "v3.26.1", - "source": { - "type": "git", - "url": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer.git", - "reference": "d023ba6684055f6ea1da1352d8a02baca0426983" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/PHP-CS-Fixer/PHP-CS-Fixer/zipball/d023ba6684055f6ea1da1352d8a02baca0426983", - "reference": "d023ba6684055f6ea1da1352d8a02baca0426983", - "shasum": "" - }, - "require": { - "composer/semver": "^3.3", - "composer/xdebug-handler": "^3.0.3", - "ext-json": "*", - "ext-tokenizer": "*", - "php": "^7.4 || ^8.0", - "sebastian/diff": "^4.0 || ^5.0", - "symfony/console": "^5.4 || ^6.0", - "symfony/event-dispatcher": "^5.4 || ^6.0", - "symfony/filesystem": "^5.4 || ^6.0", - "symfony/finder": "^5.4 || ^6.0", - "symfony/options-resolver": "^5.4 || ^6.0", - "symfony/polyfill-mbstring": "^1.27", - "symfony/polyfill-php80": "^1.27", - "symfony/polyfill-php81": "^1.27", - "symfony/process": "^5.4 || ^6.0", - "symfony/stopwatch": "^5.4 || ^6.0" - }, - "require-dev": { - "facile-it/paraunit": "^1.3 || ^2.0", - "justinrainbow/json-schema": "^5.2", - "keradus/cli-executor": "^2.0", - "mikey179/vfsstream": "^1.6.11", - "php-coveralls/php-coveralls": "^2.5.3", - "php-cs-fixer/accessible-object": "^1.1", - "php-cs-fixer/phpunit-constraint-isidenticalstring": "^1.2", - "php-cs-fixer/phpunit-constraint-xmlmatchesxsd": "^1.2.1", - "phpspec/prophecy": "^1.16", - "phpspec/prophecy-phpunit": "^2.0", - "phpunit/phpunit": "^9.5", - "phpunitgoodpractices/polyfill": "^1.6", - "phpunitgoodpractices/traits": "^1.9.2", - "symfony/phpunit-bridge": "^6.2.3", - "symfony/yaml": "^5.4 || ^6.0" - }, - "suggest": { - "ext-dom": "For handling output formats in XML", - "ext-mbstring": "For handling non-UTF8 characters." - }, - "bin": [ - "php-cs-fixer" - ], - "type": "application", - "autoload": { - "psr-4": { - "PhpCsFixer\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Dariusz Rumiński", - "email": "dariusz.ruminski@gmail.com" - } - ], - "description": "A tool to automatically fix PHP code style", - "keywords": [ - "Static code analysis", - "fixer", - "standards", - "static analysis" - ], - "support": { - "issues": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer/issues", - "source": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer/tree/v3.26.1" - }, - "funding": [ - { - "url": "https://github.com/keradus", - "type": "github" - } - ], - "time": "2023-09-08T19:09:07+00:00" - }, - { - "name": "hamcrest/hamcrest-php", - "version": "v2.0.1", - "source": { - "type": "git", - "url": "https://github.com/hamcrest/hamcrest-php.git", - "reference": "8c3d0a3f6af734494ad8f6fbbee0ba92422859f3" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/hamcrest/hamcrest-php/zipball/8c3d0a3f6af734494ad8f6fbbee0ba92422859f3", - "reference": "8c3d0a3f6af734494ad8f6fbbee0ba92422859f3", - "shasum": "" - }, - "require": { - "php": "^5.3|^7.0|^8.0" - }, - "replace": { - "cordoval/hamcrest-php": "*", - "davedevelopment/hamcrest-php": "*", - "kodova/hamcrest-php": "*" - }, - "require-dev": { - "phpunit/php-file-iterator": "^1.4 || ^2.0", - "phpunit/phpunit": "^4.8.36 || ^5.7 || ^6.5 || ^7.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "2.1-dev" - } - }, - "autoload": { - "classmap": [ - "hamcrest" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "description": "This is the PHP port of Hamcrest Matchers", - "keywords": [ - "test" - ], - "support": { - "issues": "https://github.com/hamcrest/hamcrest-php/issues", - "source": "https://github.com/hamcrest/hamcrest-php/tree/v2.0.1" - }, - "time": "2020-07-09T08:09:16+00:00" - }, - { - "name": "kahlan/kahlan", - "version": "5.2.5", - "source": { - "type": "git", - "url": "https://github.com/kahlan/kahlan.git", - "reference": "b306b275316c35c96da931fb619387e82eb61760" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/kahlan/kahlan/zipball/b306b275316c35c96da931fb619387e82eb61760", - "reference": "b306b275316c35c96da931fb619387e82eb61760", - "shasum": "" - }, - "require": { - "php": ">=7.2" - }, - "require-dev": { - "rector/rector": "^0.18", - "squizlabs/php_codesniffer": "^3.4" - }, - "bin": [ - "bin/kahlan" - ], - "type": "library", - "autoload": { - "files": [ - "src/functions.php" - ], - "psr-4": { - "Kahlan\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "CrysaLEAD" - } - ], - "description": "The PHP Test Framework for Freedom, Truth and Justice.", - "keywords": [ - "BDD", - "Behavior-Driven Development", - "Monkey Patching", - "TDD", - "mock", - "stub", - "testing", - "unit test" - ], - "support": { - "issues": "https://github.com/kahlan/kahlan/issues", - "source": "https://github.com/kahlan/kahlan/tree/5.2.5" - }, - "time": "2023-09-12T10:35:16+00:00" - }, - { - "name": "mikey179/vfsstream", - "version": "v1.6.11", - "source": { - "type": "git", - "url": "https://github.com/bovigo/vfsStream.git", - "reference": "17d16a85e6c26ce1f3e2fa9ceeacdc2855db1e9f" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/bovigo/vfsStream/zipball/17d16a85e6c26ce1f3e2fa9ceeacdc2855db1e9f", - "reference": "17d16a85e6c26ce1f3e2fa9ceeacdc2855db1e9f", - "shasum": "" - }, - "require": { - "php": ">=5.3.0" - }, - "require-dev": { - "phpunit/phpunit": "^4.5|^5.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.6.x-dev" - } - }, - "autoload": { - "psr-0": { - "org\\bovigo\\vfs\\": "src/main/php" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Frank Kleine", - "homepage": "http://frankkleine.de/", - "role": "Developer" - } - ], - "description": "Virtual file system to mock the real file system in unit tests.", - "homepage": "http://vfs.bovigo.org/", - "support": { - "issues": "https://github.com/bovigo/vfsStream/issues", - "source": "https://github.com/bovigo/vfsStream/tree/master", - "wiki": "https://github.com/bovigo/vfsStream/wiki" - }, - "time": "2022-02-23T02:02:42+00:00" - }, - { - "name": "mockery/mockery", - "version": "1.6.6", - "source": { - "type": "git", - "url": "https://github.com/mockery/mockery.git", - "reference": "b8e0bb7d8c604046539c1115994632c74dcb361e" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/mockery/mockery/zipball/b8e0bb7d8c604046539c1115994632c74dcb361e", - "reference": "b8e0bb7d8c604046539c1115994632c74dcb361e", - "shasum": "" - }, - "require": { - "hamcrest/hamcrest-php": "^2.0.1", - "lib-pcre": ">=7.0", - "php": ">=7.3" - }, - "conflict": { - "phpunit/phpunit": "<8.0" - }, - "require-dev": { - "phpunit/phpunit": "^8.5 || ^9.6.10", - "psalm/plugin-phpunit": "^0.18.4", - "symplify/easy-coding-standard": "^11.5.0", - "vimeo/psalm": "^4.30" - }, - "type": "library", - "autoload": { - "files": [ - "library/helpers.php", - "library/Mockery.php" - ], - "psr-4": { - "Mockery\\": "library/Mockery" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Pádraic Brady", - "email": "padraic.brady@gmail.com", - "homepage": "https://github.com/padraic", - "role": "Author" - }, - { - "name": "Dave Marshall", - "email": "dave.marshall@atstsolutions.co.uk", - "homepage": "https://davedevelopment.co.uk", - "role": "Developer" - }, - { - "name": "Nathanael Esayeas", - "email": "nathanael.esayeas@protonmail.com", - "homepage": "https://github.com/ghostwriter", - "role": "Lead Developer" - } - ], - "description": "Mockery is a simple yet flexible PHP mock object framework", - "homepage": "https://github.com/mockery/mockery", - "keywords": [ - "BDD", - "TDD", - "library", - "mock", - "mock objects", - "mockery", - "stub", - "test", - "test double", - "testing" - ], - "support": { - "docs": "https://docs.mockery.io/", - "issues": "https://github.com/mockery/mockery/issues", - "rss": "https://github.com/mockery/mockery/releases.atom", - "security": "https://github.com/mockery/mockery/security/advisories", - "source": "https://github.com/mockery/mockery" - }, - "time": "2023-08-09T00:03:52+00:00" - }, - { - "name": "myclabs/deep-copy", - "version": "1.11.1", - "source": { - "type": "git", - "url": "https://github.com/myclabs/DeepCopy.git", - "reference": "7284c22080590fb39f2ffa3e9057f10a4ddd0e0c" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/7284c22080590fb39f2ffa3e9057f10a4ddd0e0c", - "reference": "7284c22080590fb39f2ffa3e9057f10a4ddd0e0c", - "shasum": "" - }, - "require": { - "php": "^7.1 || ^8.0" - }, - "conflict": { - "doctrine/collections": "<1.6.8", - "doctrine/common": "<2.13.3 || >=3,<3.2.2" - }, - "require-dev": { - "doctrine/collections": "^1.6.8", - "doctrine/common": "^2.13.3 || ^3.2.2", - "phpunit/phpunit": "^7.5.20 || ^8.5.23 || ^9.5.13" - }, - "type": "library", - "autoload": { - "files": [ - "src/DeepCopy/deep_copy.php" - ], - "psr-4": { - "DeepCopy\\": "src/DeepCopy/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "description": "Create deep copies (clones) of your objects", - "keywords": [ - "clone", - "copy", - "duplicate", - "object", - "object graph" - ], - "support": { - "issues": "https://github.com/myclabs/DeepCopy/issues", - "source": "https://github.com/myclabs/DeepCopy/tree/1.11.1" - }, - "funding": [ - { - "url": "https://tidelift.com/funding/github/packagist/myclabs/deep-copy", - "type": "tidelift" - } - ], - "time": "2023-03-08T13:26:56+00:00" - }, - { - "name": "netresearch/jsonmapper", - "version": "v4.2.0", - "source": { - "type": "git", - "url": "https://github.com/cweiske/jsonmapper.git", - "reference": "f60565f8c0566a31acf06884cdaa591867ecc956" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/cweiske/jsonmapper/zipball/f60565f8c0566a31acf06884cdaa591867ecc956", - "reference": "f60565f8c0566a31acf06884cdaa591867ecc956", - "shasum": "" - }, - "require": { - "ext-json": "*", - "ext-pcre": "*", - "ext-reflection": "*", - "ext-spl": "*", - "php": ">=7.1" - }, - "require-dev": { - "phpunit/phpunit": "~7.5 || ~8.0 || ~9.0", - "squizlabs/php_codesniffer": "~3.5" - }, - "type": "library", - "autoload": { - "psr-0": { - "JsonMapper": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "OSL-3.0" - ], - "authors": [ - { - "name": "Christian Weiske", - "email": "cweiske@cweiske.de", - "homepage": "http://github.com/cweiske/jsonmapper/", - "role": "Developer" - } - ], - "description": "Map nested JSON structures onto PHP classes", - "support": { - "email": "cweiske@cweiske.de", - "issues": "https://github.com/cweiske/jsonmapper/issues", - "source": "https://github.com/cweiske/jsonmapper/tree/v4.2.0" - }, - "time": "2023-04-09T17:37:40+00:00" - }, - { - "name": "nikic/php-parser", - "version": "v4.17.1", - "source": { - "type": "git", - "url": "https://github.com/nikic/PHP-Parser.git", - "reference": "a6303e50c90c355c7eeee2c4a8b27fe8dc8fef1d" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/a6303e50c90c355c7eeee2c4a8b27fe8dc8fef1d", - "reference": "a6303e50c90c355c7eeee2c4a8b27fe8dc8fef1d", - "shasum": "" - }, - "require": { - "ext-tokenizer": "*", - "php": ">=7.0" - }, - "require-dev": { - "ircmaxell/php-yacc": "^0.0.7", - "phpunit/phpunit": "^6.5 || ^7.0 || ^8.0 || ^9.0" - }, - "bin": [ - "bin/php-parse" - ], - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "4.9-dev" - } - }, - "autoload": { - "psr-4": { - "PhpParser\\": "lib/PhpParser" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Nikita Popov" - } - ], - "description": "A PHP parser written in PHP", - "keywords": [ - "parser", - "php" - ], - "support": { - "issues": "https://github.com/nikic/PHP-Parser/issues", - "source": "https://github.com/nikic/PHP-Parser/tree/v4.17.1" - }, - "time": "2023-08-13T19:53:39+00:00" - }, - { - "name": "phar-io/manifest", - "version": "2.0.3", - "source": { - "type": "git", - "url": "https://github.com/phar-io/manifest.git", - "reference": "97803eca37d319dfa7826cc2437fc020857acb53" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/phar-io/manifest/zipball/97803eca37d319dfa7826cc2437fc020857acb53", - "reference": "97803eca37d319dfa7826cc2437fc020857acb53", - "shasum": "" - }, - "require": { - "ext-dom": "*", - "ext-phar": "*", - "ext-xmlwriter": "*", - "phar-io/version": "^3.0.1", - "php": "^7.2 || ^8.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "2.0.x-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Arne Blankerts", - "email": "arne@blankerts.de", - "role": "Developer" - }, - { - "name": "Sebastian Heuer", - "email": "sebastian@phpeople.de", - "role": "Developer" - }, - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "Developer" - } - ], - "description": "Component for reading phar.io manifest information from a PHP Archive (PHAR)", - "support": { - "issues": "https://github.com/phar-io/manifest/issues", - "source": "https://github.com/phar-io/manifest/tree/2.0.3" - }, - "time": "2021-07-20T11:28:43+00:00" - }, - { - "name": "phar-io/version", - "version": "3.2.1", - "source": { - "type": "git", - "url": "https://github.com/phar-io/version.git", - "reference": "4f7fd7836c6f332bb2933569e566a0d6c4cbed74" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/phar-io/version/zipball/4f7fd7836c6f332bb2933569e566a0d6c4cbed74", - "reference": "4f7fd7836c6f332bb2933569e566a0d6c4cbed74", - "shasum": "" - }, - "require": { - "php": "^7.2 || ^8.0" - }, - "type": "library", - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Arne Blankerts", - "email": "arne@blankerts.de", - "role": "Developer" - }, - { - "name": "Sebastian Heuer", - "email": "sebastian@phpeople.de", - "role": "Developer" - }, - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "Developer" - } - ], - "description": "Library for handling version information and constraints", - "support": { - "issues": "https://github.com/phar-io/version/issues", - "source": "https://github.com/phar-io/version/tree/3.2.1" - }, - "time": "2022-02-21T01:04:05+00:00" - }, - { - "name": "phpdocumentor/reflection-common", - "version": "2.2.0", - "source": { - "type": "git", - "url": "https://github.com/phpDocumentor/ReflectionCommon.git", - "reference": "1d01c49d4ed62f25aa84a747ad35d5a16924662b" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/phpDocumentor/ReflectionCommon/zipball/1d01c49d4ed62f25aa84a747ad35d5a16924662b", - "reference": "1d01c49d4ed62f25aa84a747ad35d5a16924662b", - "shasum": "" - }, - "require": { - "php": "^7.2 || ^8.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-2.x": "2.x-dev" - } - }, - "autoload": { - "psr-4": { - "phpDocumentor\\Reflection\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Jaap van Otterdijk", - "email": "opensource@ijaap.nl" - } - ], - "description": "Common reflection classes used by phpdocumentor to reflect the code structure", - "homepage": "http://www.phpdoc.org", - "keywords": [ - "FQSEN", - "phpDocumentor", - "phpdoc", - "reflection", - "static analysis" - ], - "support": { - "issues": "https://github.com/phpDocumentor/ReflectionCommon/issues", - "source": "https://github.com/phpDocumentor/ReflectionCommon/tree/2.x" - }, - "time": "2020-06-27T09:03:43+00:00" - }, - { - "name": "phpdocumentor/reflection-docblock", - "version": "5.3.0", - "source": { - "type": "git", - "url": "https://github.com/phpDocumentor/ReflectionDocBlock.git", - "reference": "622548b623e81ca6d78b721c5e029f4ce664f170" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/622548b623e81ca6d78b721c5e029f4ce664f170", - "reference": "622548b623e81ca6d78b721c5e029f4ce664f170", - "shasum": "" - }, - "require": { - "ext-filter": "*", - "php": "^7.2 || ^8.0", - "phpdocumentor/reflection-common": "^2.2", - "phpdocumentor/type-resolver": "^1.3", - "webmozart/assert": "^1.9.1" - }, - "require-dev": { - "mockery/mockery": "~1.3.2", - "psalm/phar": "^4.8" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "5.x-dev" - } - }, - "autoload": { - "psr-4": { - "phpDocumentor\\Reflection\\": "src" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Mike van Riel", - "email": "me@mikevanriel.com" - }, - { - "name": "Jaap van Otterdijk", - "email": "account@ijaap.nl" - } - ], - "description": "With this component, a library can provide support for annotations via DocBlocks or otherwise retrieve information that is embedded in a DocBlock.", - "support": { - "issues": "https://github.com/phpDocumentor/ReflectionDocBlock/issues", - "source": "https://github.com/phpDocumentor/ReflectionDocBlock/tree/5.3.0" - }, - "time": "2021-10-19T17:43:47+00:00" - }, - { - "name": "phpdocumentor/type-resolver", - "version": "1.7.3", - "source": { - "type": "git", - "url": "https://github.com/phpDocumentor/TypeResolver.git", - "reference": "3219c6ee25c9ea71e3d9bbaf39c67c9ebd499419" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/phpDocumentor/TypeResolver/zipball/3219c6ee25c9ea71e3d9bbaf39c67c9ebd499419", - "reference": "3219c6ee25c9ea71e3d9bbaf39c67c9ebd499419", - "shasum": "" - }, - "require": { - "doctrine/deprecations": "^1.0", - "php": "^7.4 || ^8.0", - "phpdocumentor/reflection-common": "^2.0", - "phpstan/phpdoc-parser": "^1.13" - }, - "require-dev": { - "ext-tokenizer": "*", - "phpbench/phpbench": "^1.2", - "phpstan/extension-installer": "^1.1", - "phpstan/phpstan": "^1.8", - "phpstan/phpstan-phpunit": "^1.1", - "phpunit/phpunit": "^9.5", - "rector/rector": "^0.13.9", - "vimeo/psalm": "^4.25" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-1.x": "1.x-dev" - } - }, - "autoload": { - "psr-4": { - "phpDocumentor\\Reflection\\": "src" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Mike van Riel", - "email": "me@mikevanriel.com" - } - ], - "description": "A PSR-5 based resolver of Class names, Types and Structural Element Names", - "support": { - "issues": "https://github.com/phpDocumentor/TypeResolver/issues", - "source": "https://github.com/phpDocumentor/TypeResolver/tree/1.7.3" - }, - "time": "2023-08-12T11:01:26+00:00" - }, - { - "name": "phpstan/phpdoc-parser", - "version": "1.24.2", - "source": { - "type": "git", - "url": "https://github.com/phpstan/phpdoc-parser.git", - "reference": "bcad8d995980440892759db0c32acae7c8e79442" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/phpstan/phpdoc-parser/zipball/bcad8d995980440892759db0c32acae7c8e79442", - "reference": "bcad8d995980440892759db0c32acae7c8e79442", - "shasum": "" - }, - "require": { - "php": "^7.2 || ^8.0" - }, - "require-dev": { - "doctrine/annotations": "^2.0", - "nikic/php-parser": "^4.15", - "php-parallel-lint/php-parallel-lint": "^1.2", - "phpstan/extension-installer": "^1.0", - "phpstan/phpstan": "^1.5", - "phpstan/phpstan-phpunit": "^1.1", - "phpstan/phpstan-strict-rules": "^1.0", - "phpunit/phpunit": "^9.5", - "symfony/process": "^5.2" - }, - "type": "library", - "autoload": { - "psr-4": { - "PHPStan\\PhpDocParser\\": [ - "src/" - ] - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "description": "PHPDoc parser with support for nullable, intersection and generic types", - "support": { - "issues": "https://github.com/phpstan/phpdoc-parser/issues", - "source": "https://github.com/phpstan/phpdoc-parser/tree/1.24.2" - }, - "time": "2023-09-26T12:28:12+00:00" - }, - { - "name": "phpunit/php-code-coverage", - "version": "9.2.28", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/php-code-coverage.git", - "reference": "7134a5ccaaf0f1c92a4f5501a6c9f98ac4dcc0ef" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/7134a5ccaaf0f1c92a4f5501a6c9f98ac4dcc0ef", - "reference": "7134a5ccaaf0f1c92a4f5501a6c9f98ac4dcc0ef", - "shasum": "" - }, - "require": { - "ext-dom": "*", - "ext-libxml": "*", - "ext-xmlwriter": "*", - "nikic/php-parser": "^4.15", - "php": ">=7.3", - "phpunit/php-file-iterator": "^3.0.3", - "phpunit/php-text-template": "^2.0.2", - "sebastian/code-unit-reverse-lookup": "^2.0.2", - "sebastian/complexity": "^2.0", - "sebastian/environment": "^5.1.2", - "sebastian/lines-of-code": "^1.0.3", - "sebastian/version": "^3.0.1", - "theseer/tokenizer": "^1.2.0" - }, - "require-dev": { - "phpunit/phpunit": "^9.3" - }, - "suggest": { - "ext-pcov": "PHP extension that provides line coverage", - "ext-xdebug": "PHP extension that provides line coverage as well as branch and path coverage" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "9.2-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "lead" - } - ], - "description": "Library that provides collection, processing, and rendering functionality for PHP code coverage information.", - "homepage": "https://github.com/sebastianbergmann/php-code-coverage", - "keywords": [ - "coverage", - "testing", - "xunit" - ], - "support": { - "issues": "https://github.com/sebastianbergmann/php-code-coverage/issues", - "security": "https://github.com/sebastianbergmann/php-code-coverage/security/policy", - "source": "https://github.com/sebastianbergmann/php-code-coverage/tree/9.2.28" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2023-09-12T14:36:20+00:00" - }, - { - "name": "phpunit/php-file-iterator", - "version": "3.0.6", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/php-file-iterator.git", - "reference": "cf1c2e7c203ac650e352f4cc675a7021e7d1b3cf" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/cf1c2e7c203ac650e352f4cc675a7021e7d1b3cf", - "reference": "cf1c2e7c203ac650e352f4cc675a7021e7d1b3cf", - "shasum": "" - }, - "require": { - "php": ">=7.3" - }, - "require-dev": { - "phpunit/phpunit": "^9.3" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "3.0-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "lead" - } - ], - "description": "FilterIterator implementation that filters files based on a list of suffixes.", - "homepage": "https://github.com/sebastianbergmann/php-file-iterator/", - "keywords": [ - "filesystem", - "iterator" - ], - "support": { - "issues": "https://github.com/sebastianbergmann/php-file-iterator/issues", - "source": "https://github.com/sebastianbergmann/php-file-iterator/tree/3.0.6" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2021-12-02T12:48:52+00:00" - }, - { - "name": "phpunit/php-invoker", - "version": "3.1.1", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/php-invoker.git", - "reference": "5a10147d0aaf65b58940a0b72f71c9ac0423cc67" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-invoker/zipball/5a10147d0aaf65b58940a0b72f71c9ac0423cc67", - "reference": "5a10147d0aaf65b58940a0b72f71c9ac0423cc67", - "shasum": "" - }, - "require": { - "php": ">=7.3" - }, - "require-dev": { - "ext-pcntl": "*", - "phpunit/phpunit": "^9.3" - }, - "suggest": { - "ext-pcntl": "*" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "3.1-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "lead" - } - ], - "description": "Invoke callables with a timeout", - "homepage": "https://github.com/sebastianbergmann/php-invoker/", - "keywords": [ - "process" - ], - "support": { - "issues": "https://github.com/sebastianbergmann/php-invoker/issues", - "source": "https://github.com/sebastianbergmann/php-invoker/tree/3.1.1" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2020-09-28T05:58:55+00:00" - }, - { - "name": "phpunit/php-text-template", - "version": "2.0.4", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/php-text-template.git", - "reference": "5da5f67fc95621df9ff4c4e5a84d6a8a2acf7c28" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-text-template/zipball/5da5f67fc95621df9ff4c4e5a84d6a8a2acf7c28", - "reference": "5da5f67fc95621df9ff4c4e5a84d6a8a2acf7c28", - "shasum": "" - }, - "require": { - "php": ">=7.3" - }, - "require-dev": { - "phpunit/phpunit": "^9.3" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "2.0-dev" - } - }, - "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": "https://github.com/sebastianbergmann/php-text-template/", - "keywords": [ - "template" - ], - "support": { - "issues": "https://github.com/sebastianbergmann/php-text-template/issues", - "source": "https://github.com/sebastianbergmann/php-text-template/tree/2.0.4" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2020-10-26T05:33:50+00:00" - }, - { - "name": "phpunit/php-timer", - "version": "5.0.3", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/php-timer.git", - "reference": "5a63ce20ed1b5bf577850e2c4e87f4aa902afbd2" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/5a63ce20ed1b5bf577850e2c4e87f4aa902afbd2", - "reference": "5a63ce20ed1b5bf577850e2c4e87f4aa902afbd2", - "shasum": "" - }, - "require": { - "php": ">=7.3" - }, - "require-dev": { - "phpunit/phpunit": "^9.3" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "5.0-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "lead" - } - ], - "description": "Utility class for timing", - "homepage": "https://github.com/sebastianbergmann/php-timer/", - "keywords": [ - "timer" - ], - "support": { - "issues": "https://github.com/sebastianbergmann/php-timer/issues", - "source": "https://github.com/sebastianbergmann/php-timer/tree/5.0.3" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2020-10-26T13:16:10+00:00" - }, - { - "name": "phpunit/phpunit", - "version": "9.6.12", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/phpunit.git", - "reference": "a122c2ebd469b751d774aa0f613dc0d67697653f" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/a122c2ebd469b751d774aa0f613dc0d67697653f", - "reference": "a122c2ebd469b751d774aa0f613dc0d67697653f", - "shasum": "" - }, - "require": { - "doctrine/instantiator": "^1.3.1 || ^2", - "ext-dom": "*", - "ext-json": "*", - "ext-libxml": "*", - "ext-mbstring": "*", - "ext-xml": "*", - "ext-xmlwriter": "*", - "myclabs/deep-copy": "^1.10.1", - "phar-io/manifest": "^2.0.3", - "phar-io/version": "^3.0.2", - "php": ">=7.3", - "phpunit/php-code-coverage": "^9.2.28", - "phpunit/php-file-iterator": "^3.0.5", - "phpunit/php-invoker": "^3.1.1", - "phpunit/php-text-template": "^2.0.3", - "phpunit/php-timer": "^5.0.2", - "sebastian/cli-parser": "^1.0.1", - "sebastian/code-unit": "^1.0.6", - "sebastian/comparator": "^4.0.8", - "sebastian/diff": "^4.0.3", - "sebastian/environment": "^5.1.3", - "sebastian/exporter": "^4.0.5", - "sebastian/global-state": "^5.0.1", - "sebastian/object-enumerator": "^4.0.3", - "sebastian/resource-operations": "^3.0.3", - "sebastian/type": "^3.2", - "sebastian/version": "^3.0.2" - }, - "suggest": { - "ext-soap": "To be able to generate mocks based on WSDL files", - "ext-xdebug": "PHP extension that provides line coverage as well as branch and path coverage" - }, - "bin": [ - "phpunit" - ], - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "9.6-dev" - } - }, - "autoload": { - "files": [ - "src/Framework/Assert/Functions.php" - ], - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "lead" - } - ], - "description": "The PHP Unit Testing framework.", - "homepage": "https://phpunit.de/", - "keywords": [ - "phpunit", - "testing", - "xunit" - ], - "support": { - "issues": "https://github.com/sebastianbergmann/phpunit/issues", - "security": "https://github.com/sebastianbergmann/phpunit/security/policy", - "source": "https://github.com/sebastianbergmann/phpunit/tree/9.6.12" - }, - "funding": [ - { - "url": "https://phpunit.de/sponsors.html", - "type": "custom" - }, - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/phpunit/phpunit", - "type": "tidelift" - } - ], - "time": "2023-09-12T14:39:31+00:00" - }, - { - "name": "psr/container", - "version": "1.1.2", - "source": { - "type": "git", - "url": "https://github.com/php-fig/container.git", - "reference": "513e0666f7216c7459170d56df27dfcefe1689ea" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/php-fig/container/zipball/513e0666f7216c7459170d56df27dfcefe1689ea", - "reference": "513e0666f7216c7459170d56df27dfcefe1689ea", - "shasum": "" - }, - "require": { - "php": ">=7.4.0" - }, - "type": "library", - "autoload": { - "psr-4": { - "Psr\\Container\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "PHP-FIG", - "homepage": "https://www.php-fig.org/" - } - ], - "description": "Common Container Interface (PHP FIG PSR-11)", - "homepage": "https://github.com/php-fig/container", - "keywords": [ - "PSR-11", - "container", - "container-interface", - "container-interop", - "psr" - ], - "support": { - "issues": "https://github.com/php-fig/container/issues", - "source": "https://github.com/php-fig/container/tree/1.1.2" - }, - "time": "2021-11-05T16:50:12+00:00" - }, - { - "name": "psr/event-dispatcher", - "version": "1.0.0", - "source": { - "type": "git", - "url": "https://github.com/php-fig/event-dispatcher.git", - "reference": "dbefd12671e8a14ec7f180cab83036ed26714bb0" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/php-fig/event-dispatcher/zipball/dbefd12671e8a14ec7f180cab83036ed26714bb0", - "reference": "dbefd12671e8a14ec7f180cab83036ed26714bb0", - "shasum": "" - }, - "require": { - "php": ">=7.2.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.0.x-dev" - } - }, - "autoload": { - "psr-4": { - "Psr\\EventDispatcher\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "PHP-FIG", - "homepage": "http://www.php-fig.org/" - } - ], - "description": "Standard interfaces for event handling.", - "keywords": [ - "events", - "psr", - "psr-14" - ], - "support": { - "issues": "https://github.com/php-fig/event-dispatcher/issues", - "source": "https://github.com/php-fig/event-dispatcher/tree/1.0.0" - }, - "time": "2019-01-08T18:20:26+00:00" - }, - { - "name": "psr/log", - "version": "1.1.4", - "source": { - "type": "git", - "url": "https://github.com/php-fig/log.git", - "reference": "d49695b909c3b7628b6289db5479a1c204601f11" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/php-fig/log/zipball/d49695b909c3b7628b6289db5479a1c204601f11", - "reference": "d49695b909c3b7628b6289db5479a1c204601f11", - "shasum": "" - }, - "require": { - "php": ">=5.3.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.1.x-dev" - } - }, - "autoload": { - "psr-4": { - "Psr\\Log\\": "Psr/Log/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "PHP-FIG", - "homepage": "https://www.php-fig.org/" - } - ], - "description": "Common interface for logging libraries", - "homepage": "https://github.com/php-fig/log", - "keywords": [ - "log", - "psr", - "psr-3" - ], - "support": { - "source": "https://github.com/php-fig/log/tree/1.1.4" - }, - "time": "2021-05-03T11:20:27+00:00" - }, - { - "name": "sebastian/cli-parser", - "version": "1.0.1", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/cli-parser.git", - "reference": "442e7c7e687e42adc03470c7b668bc4b2402c0b2" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/cli-parser/zipball/442e7c7e687e42adc03470c7b668bc4b2402c0b2", - "reference": "442e7c7e687e42adc03470c7b668bc4b2402c0b2", - "shasum": "" - }, - "require": { - "php": ">=7.3" - }, - "require-dev": { - "phpunit/phpunit": "^9.3" - }, - "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": "sebastian@phpunit.de", - "role": "lead" - } - ], - "description": "Library for parsing CLI options", - "homepage": "https://github.com/sebastianbergmann/cli-parser", - "support": { - "issues": "https://github.com/sebastianbergmann/cli-parser/issues", - "source": "https://github.com/sebastianbergmann/cli-parser/tree/1.0.1" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2020-09-28T06:08:49+00:00" - }, - { - "name": "sebastian/code-unit", - "version": "1.0.8", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/code-unit.git", - "reference": "1fc9f64c0927627ef78ba436c9b17d967e68e120" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/code-unit/zipball/1fc9f64c0927627ef78ba436c9b17d967e68e120", - "reference": "1fc9f64c0927627ef78ba436c9b17d967e68e120", - "shasum": "" - }, - "require": { - "php": ">=7.3" - }, - "require-dev": { - "phpunit/phpunit": "^9.3" - }, - "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": "sebastian@phpunit.de", - "role": "lead" - } - ], - "description": "Collection of value objects that represent the PHP code units", - "homepage": "https://github.com/sebastianbergmann/code-unit", - "support": { - "issues": "https://github.com/sebastianbergmann/code-unit/issues", - "source": "https://github.com/sebastianbergmann/code-unit/tree/1.0.8" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2020-10-26T13:08:54+00:00" - }, - { - "name": "sebastian/code-unit-reverse-lookup", - "version": "2.0.3", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/code-unit-reverse-lookup.git", - "reference": "ac91f01ccec49fb77bdc6fd1e548bc70f7faa3e5" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/code-unit-reverse-lookup/zipball/ac91f01ccec49fb77bdc6fd1e548bc70f7faa3e5", - "reference": "ac91f01ccec49fb77bdc6fd1e548bc70f7faa3e5", - "shasum": "" - }, - "require": { - "php": ">=7.3" - }, - "require-dev": { - "phpunit/phpunit": "^9.3" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "2.0-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" - } - ], - "description": "Looks up which function or method a line of code belongs to", - "homepage": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/", - "support": { - "issues": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/issues", - "source": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/tree/2.0.3" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2020-09-28T05:30:19+00:00" - }, - { - "name": "sebastian/comparator", - "version": "4.0.8", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/comparator.git", - "reference": "fa0f136dd2334583309d32b62544682ee972b51a" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/fa0f136dd2334583309d32b62544682ee972b51a", - "reference": "fa0f136dd2334583309d32b62544682ee972b51a", - "shasum": "" - }, - "require": { - "php": ">=7.3", - "sebastian/diff": "^4.0", - "sebastian/exporter": "^4.0" - }, - "require-dev": { - "phpunit/phpunit": "^9.3" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "4.0-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" - }, - { - "name": "Jeff Welch", - "email": "whatthejeff@gmail.com" - }, - { - "name": "Volker Dusch", - "email": "github@wallbash.com" - }, - { - "name": "Bernhard Schussek", - "email": "bschussek@2bepublished.at" - } - ], - "description": "Provides the functionality to compare PHP values for equality", - "homepage": "https://github.com/sebastianbergmann/comparator", - "keywords": [ - "comparator", - "compare", - "equality" - ], - "support": { - "issues": "https://github.com/sebastianbergmann/comparator/issues", - "source": "https://github.com/sebastianbergmann/comparator/tree/4.0.8" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2022-09-14T12:41:17+00:00" - }, - { - "name": "sebastian/complexity", - "version": "2.0.2", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/complexity.git", - "reference": "739b35e53379900cc9ac327b2147867b8b6efd88" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/complexity/zipball/739b35e53379900cc9ac327b2147867b8b6efd88", - "reference": "739b35e53379900cc9ac327b2147867b8b6efd88", - "shasum": "" - }, - "require": { - "nikic/php-parser": "^4.7", - "php": ">=7.3" - }, - "require-dev": { - "phpunit/phpunit": "^9.3" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "2.0-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "lead" - } - ], - "description": "Library for calculating the complexity of PHP code units", - "homepage": "https://github.com/sebastianbergmann/complexity", - "support": { - "issues": "https://github.com/sebastianbergmann/complexity/issues", - "source": "https://github.com/sebastianbergmann/complexity/tree/2.0.2" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2020-10-26T15:52:27+00:00" - }, - { - "name": "sebastian/diff", - "version": "4.0.5", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/diff.git", - "reference": "74be17022044ebaaecfdf0c5cd504fc9cd5a7131" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/74be17022044ebaaecfdf0c5cd504fc9cd5a7131", - "reference": "74be17022044ebaaecfdf0c5cd504fc9cd5a7131", - "shasum": "" - }, - "require": { - "php": ">=7.3" - }, - "require-dev": { - "phpunit/phpunit": "^9.3", - "symfony/process": "^4.2 || ^5" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "4.0-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" - }, - { - "name": "Kore Nordmann", - "email": "mail@kore-nordmann.de" - } - ], - "description": "Diff implementation", - "homepage": "https://github.com/sebastianbergmann/diff", - "keywords": [ - "diff", - "udiff", - "unidiff", - "unified diff" - ], - "support": { - "issues": "https://github.com/sebastianbergmann/diff/issues", - "source": "https://github.com/sebastianbergmann/diff/tree/4.0.5" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2023-05-07T05:35:17+00:00" - }, - { - "name": "sebastian/environment", - "version": "5.1.5", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/environment.git", - "reference": "830c43a844f1f8d5b7a1f6d6076b784454d8b7ed" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/830c43a844f1f8d5b7a1f6d6076b784454d8b7ed", - "reference": "830c43a844f1f8d5b7a1f6d6076b784454d8b7ed", - "shasum": "" - }, - "require": { - "php": ">=7.3" - }, - "require-dev": { - "phpunit/phpunit": "^9.3" - }, - "suggest": { - "ext-posix": "*" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "5.1-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" - } - ], - "description": "Provides functionality to handle HHVM/PHP environments", - "homepage": "http://www.github.com/sebastianbergmann/environment", - "keywords": [ - "Xdebug", - "environment", - "hhvm" - ], - "support": { - "issues": "https://github.com/sebastianbergmann/environment/issues", - "source": "https://github.com/sebastianbergmann/environment/tree/5.1.5" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2023-02-03T06:03:51+00:00" - }, - { - "name": "sebastian/exporter", - "version": "4.0.5", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/exporter.git", - "reference": "ac230ed27f0f98f597c8a2b6eb7ac563af5e5b9d" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/ac230ed27f0f98f597c8a2b6eb7ac563af5e5b9d", - "reference": "ac230ed27f0f98f597c8a2b6eb7ac563af5e5b9d", - "shasum": "" - }, - "require": { - "php": ">=7.3", - "sebastian/recursion-context": "^4.0" - }, - "require-dev": { - "ext-mbstring": "*", - "phpunit/phpunit": "^9.3" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "4.0-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" - }, - { - "name": "Jeff Welch", - "email": "whatthejeff@gmail.com" - }, - { - "name": "Volker Dusch", - "email": "github@wallbash.com" - }, - { - "name": "Adam Harvey", - "email": "aharvey@php.net" - }, - { - "name": "Bernhard Schussek", - "email": "bschussek@gmail.com" - } - ], - "description": "Provides the functionality to export PHP variables for visualization", - "homepage": "https://www.github.com/sebastianbergmann/exporter", - "keywords": [ - "export", - "exporter" - ], - "support": { - "issues": "https://github.com/sebastianbergmann/exporter/issues", - "source": "https://github.com/sebastianbergmann/exporter/tree/4.0.5" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2022-09-14T06:03:37+00:00" - }, - { - "name": "sebastian/global-state", - "version": "5.0.6", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/global-state.git", - "reference": "bde739e7565280bda77be70044ac1047bc007e34" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/bde739e7565280bda77be70044ac1047bc007e34", - "reference": "bde739e7565280bda77be70044ac1047bc007e34", - "shasum": "" - }, - "require": { - "php": ">=7.3", - "sebastian/object-reflector": "^2.0", - "sebastian/recursion-context": "^4.0" - }, - "require-dev": { - "ext-dom": "*", - "phpunit/phpunit": "^9.3" - }, - "suggest": { - "ext-uopz": "*" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "5.0-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" - } - ], - "description": "Snapshotting of global state", - "homepage": "http://www.github.com/sebastianbergmann/global-state", - "keywords": [ - "global state" - ], - "support": { - "issues": "https://github.com/sebastianbergmann/global-state/issues", - "source": "https://github.com/sebastianbergmann/global-state/tree/5.0.6" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2023-08-02T09:26:13+00:00" - }, - { - "name": "sebastian/lines-of-code", - "version": "1.0.3", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/lines-of-code.git", - "reference": "c1c2e997aa3146983ed888ad08b15470a2e22ecc" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/lines-of-code/zipball/c1c2e997aa3146983ed888ad08b15470a2e22ecc", - "reference": "c1c2e997aa3146983ed888ad08b15470a2e22ecc", - "shasum": "" - }, - "require": { - "nikic/php-parser": "^4.6", - "php": ">=7.3" - }, - "require-dev": { - "phpunit/phpunit": "^9.3" - }, - "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": "sebastian@phpunit.de", - "role": "lead" - } - ], - "description": "Library for counting the lines of code in PHP source code", - "homepage": "https://github.com/sebastianbergmann/lines-of-code", - "support": { - "issues": "https://github.com/sebastianbergmann/lines-of-code/issues", - "source": "https://github.com/sebastianbergmann/lines-of-code/tree/1.0.3" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2020-11-28T06:42:11+00:00" - }, - { - "name": "sebastian/object-enumerator", - "version": "4.0.4", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/object-enumerator.git", - "reference": "5c9eeac41b290a3712d88851518825ad78f45c71" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/object-enumerator/zipball/5c9eeac41b290a3712d88851518825ad78f45c71", - "reference": "5c9eeac41b290a3712d88851518825ad78f45c71", - "shasum": "" - }, - "require": { - "php": ">=7.3", - "sebastian/object-reflector": "^2.0", - "sebastian/recursion-context": "^4.0" - }, - "require-dev": { - "phpunit/phpunit": "^9.3" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "4.0-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" - } - ], - "description": "Traverses array structures and object graphs to enumerate all referenced objects", - "homepage": "https://github.com/sebastianbergmann/object-enumerator/", - "support": { - "issues": "https://github.com/sebastianbergmann/object-enumerator/issues", - "source": "https://github.com/sebastianbergmann/object-enumerator/tree/4.0.4" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2020-10-26T13:12:34+00:00" - }, - { - "name": "sebastian/object-reflector", - "version": "2.0.4", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/object-reflector.git", - "reference": "b4f479ebdbf63ac605d183ece17d8d7fe49c15c7" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/object-reflector/zipball/b4f479ebdbf63ac605d183ece17d8d7fe49c15c7", - "reference": "b4f479ebdbf63ac605d183ece17d8d7fe49c15c7", - "shasum": "" - }, - "require": { - "php": ">=7.3" - }, - "require-dev": { - "phpunit/phpunit": "^9.3" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "2.0-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" - } - ], - "description": "Allows reflection of object attributes, including inherited and non-public ones", - "homepage": "https://github.com/sebastianbergmann/object-reflector/", - "support": { - "issues": "https://github.com/sebastianbergmann/object-reflector/issues", - "source": "https://github.com/sebastianbergmann/object-reflector/tree/2.0.4" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2020-10-26T13:14:26+00:00" - }, - { - "name": "sebastian/recursion-context", - "version": "4.0.5", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/recursion-context.git", - "reference": "e75bd0f07204fec2a0af9b0f3cfe97d05f92efc1" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/e75bd0f07204fec2a0af9b0f3cfe97d05f92efc1", - "reference": "e75bd0f07204fec2a0af9b0f3cfe97d05f92efc1", - "shasum": "" - }, - "require": { - "php": ">=7.3" - }, - "require-dev": { - "phpunit/phpunit": "^9.3" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "4.0-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" - }, - { - "name": "Jeff Welch", - "email": "whatthejeff@gmail.com" - }, - { - "name": "Adam Harvey", - "email": "aharvey@php.net" - } - ], - "description": "Provides functionality to recursively process PHP variables", - "homepage": "https://github.com/sebastianbergmann/recursion-context", - "support": { - "issues": "https://github.com/sebastianbergmann/recursion-context/issues", - "source": "https://github.com/sebastianbergmann/recursion-context/tree/4.0.5" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2023-02-03T06:07:39+00:00" - }, - { - "name": "sebastian/resource-operations", - "version": "3.0.3", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/resource-operations.git", - "reference": "0f4443cb3a1d92ce809899753bc0d5d5a8dd19a8" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/resource-operations/zipball/0f4443cb3a1d92ce809899753bc0d5d5a8dd19a8", - "reference": "0f4443cb3a1d92ce809899753bc0d5d5a8dd19a8", - "shasum": "" - }, - "require": { - "php": ">=7.3" - }, - "require-dev": { - "phpunit/phpunit": "^9.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "3.0-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" - } - ], - "description": "Provides a list of PHP built-in functions that operate on resources", - "homepage": "https://www.github.com/sebastianbergmann/resource-operations", - "support": { - "issues": "https://github.com/sebastianbergmann/resource-operations/issues", - "source": "https://github.com/sebastianbergmann/resource-operations/tree/3.0.3" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2020-09-28T06:45:17+00:00" - }, - { - "name": "sebastian/type", - "version": "3.2.1", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/type.git", - "reference": "75e2c2a32f5e0b3aef905b9ed0b179b953b3d7c7" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/type/zipball/75e2c2a32f5e0b3aef905b9ed0b179b953b3d7c7", - "reference": "75e2c2a32f5e0b3aef905b9ed0b179b953b3d7c7", - "shasum": "" - }, - "require": { - "php": ">=7.3" - }, - "require-dev": { - "phpunit/phpunit": "^9.5" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "3.2-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "lead" - } - ], - "description": "Collection of value objects that represent the types of the PHP type system", - "homepage": "https://github.com/sebastianbergmann/type", - "support": { - "issues": "https://github.com/sebastianbergmann/type/issues", - "source": "https://github.com/sebastianbergmann/type/tree/3.2.1" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2023-02-03T06:13:03+00:00" - }, - { - "name": "sebastian/version", - "version": "3.0.2", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/version.git", - "reference": "c6c1022351a901512170118436c764e473f6de8c" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/version/zipball/c6c1022351a901512170118436c764e473f6de8c", - "reference": "c6c1022351a901512170118436c764e473f6de8c", - "shasum": "" - }, - "require": { - "php": ">=7.3" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "3.0-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "lead" - } - ], - "description": "Library that helps with managing the version number of Git-hosted PHP projects", - "homepage": "https://github.com/sebastianbergmann/version", - "support": { - "issues": "https://github.com/sebastianbergmann/version/issues", - "source": "https://github.com/sebastianbergmann/version/tree/3.0.2" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2020-09-28T06:39:44+00:00" - }, - { - "name": "spatie/array-to-xml", - "version": "2.17.1", - "source": { - "type": "git", - "url": "https://github.com/spatie/array-to-xml.git", - "reference": "5cbec9c6ab17e320c58a259f0cebe88bde4a7c46" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/spatie/array-to-xml/zipball/5cbec9c6ab17e320c58a259f0cebe88bde4a7c46", - "reference": "5cbec9c6ab17e320c58a259f0cebe88bde4a7c46", - "shasum": "" - }, - "require": { - "ext-dom": "*", - "php": "^7.4|^8.0" - }, - "require-dev": { - "mockery/mockery": "^1.2", - "pestphp/pest": "^1.21", - "phpunit/phpunit": "^9.0", - "spatie/pest-plugin-snapshots": "^1.1" - }, - "type": "library", - "autoload": { - "psr-4": { - "Spatie\\ArrayToXml\\": "src" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Freek Van der Herten", - "email": "freek@spatie.be", - "homepage": "https://freek.dev", - "role": "Developer" - } - ], - "description": "Convert an array to xml", - "homepage": "https://github.com/spatie/array-to-xml", - "keywords": [ - "array", - "convert", - "xml" - ], - "support": { - "source": "https://github.com/spatie/array-to-xml/tree/2.17.1" - }, - "funding": [ - { - "url": "https://spatie.be/open-source/support-us", - "type": "custom" - }, - { - "url": "https://github.com/spatie", - "type": "github" - } - ], - "time": "2022-12-26T08:22:07+00:00" - }, - { - "name": "symfony/console", - "version": "v5.4.28", - "source": { - "type": "git", - "url": "https://github.com/symfony/console.git", - "reference": "f4f71842f24c2023b91237c72a365306f3c58827" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/console/zipball/f4f71842f24c2023b91237c72a365306f3c58827", - "reference": "f4f71842f24c2023b91237c72a365306f3c58827", - "shasum": "" - }, - "require": { - "php": ">=7.2.5", - "symfony/deprecation-contracts": "^2.1|^3", - "symfony/polyfill-mbstring": "~1.0", - "symfony/polyfill-php73": "^1.9", - "symfony/polyfill-php80": "^1.16", - "symfony/service-contracts": "^1.1|^2|^3", - "symfony/string": "^5.1|^6.0" - }, - "conflict": { - "psr/log": ">=3", - "symfony/dependency-injection": "<4.4", - "symfony/dotenv": "<5.1", - "symfony/event-dispatcher": "<4.4", - "symfony/lock": "<4.4", - "symfony/process": "<4.4" - }, - "provide": { - "psr/log-implementation": "1.0|2.0" - }, - "require-dev": { - "psr/log": "^1|^2", - "symfony/config": "^4.4|^5.0|^6.0", - "symfony/dependency-injection": "^4.4|^5.0|^6.0", - "symfony/event-dispatcher": "^4.4|^5.0|^6.0", - "symfony/lock": "^4.4|^5.0|^6.0", - "symfony/process": "^4.4|^5.0|^6.0", - "symfony/var-dumper": "^4.4|^5.0|^6.0" - }, - "suggest": { - "psr/log": "For using the console logger", - "symfony/event-dispatcher": "", - "symfony/lock": "", - "symfony/process": "" - }, - "type": "library", - "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": "Eases the creation of beautiful and testable command line interfaces", - "homepage": "https://symfony.com", - "keywords": [ - "cli", - "command-line", - "console", - "terminal" - ], - "support": { - "source": "https://github.com/symfony/console/tree/v5.4.28" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2023-08-07T06:12:30+00:00" - }, - { - "name": "symfony/deprecation-contracts", - "version": "v2.5.2", - "source": { - "type": "git", - "url": "https://github.com/symfony/deprecation-contracts.git", - "reference": "e8b495ea28c1d97b5e0c121748d6f9b53d075c66" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/e8b495ea28c1d97b5e0c121748d6f9b53d075c66", - "reference": "e8b495ea28c1d97b5e0c121748d6f9b53d075c66", - "shasum": "" - }, - "require": { - "php": ">=7.1" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "2.5-dev" - }, - "thanks": { - "name": "symfony/contracts", - "url": "https://github.com/symfony/contracts" - } - }, - "autoload": { - "files": [ - "function.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": "A generic function and convention to trigger deprecation notices", - "homepage": "https://symfony.com", - "support": { - "source": "https://github.com/symfony/deprecation-contracts/tree/v2.5.2" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2022-01-02T09:53:40+00:00" - }, - { - "name": "symfony/event-dispatcher", - "version": "v5.4.26", - "source": { - "type": "git", - "url": "https://github.com/symfony/event-dispatcher.git", - "reference": "5dcc00e03413f05c1e7900090927bb7247cb0aac" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/5dcc00e03413f05c1e7900090927bb7247cb0aac", - "reference": "5dcc00e03413f05c1e7900090927bb7247cb0aac", - "shasum": "" - }, - "require": { - "php": ">=7.2.5", - "symfony/deprecation-contracts": "^2.1|^3", - "symfony/event-dispatcher-contracts": "^2|^3", - "symfony/polyfill-php80": "^1.16" - }, - "conflict": { - "symfony/dependency-injection": "<4.4" - }, - "provide": { - "psr/event-dispatcher-implementation": "1.0", - "symfony/event-dispatcher-implementation": "2.0" - }, - "require-dev": { - "psr/log": "^1|^2|^3", - "symfony/config": "^4.4|^5.0|^6.0", - "symfony/dependency-injection": "^4.4|^5.0|^6.0", - "symfony/error-handler": "^4.4|^5.0|^6.0", - "symfony/expression-language": "^4.4|^5.0|^6.0", - "symfony/http-foundation": "^4.4|^5.0|^6.0", - "symfony/service-contracts": "^1.1|^2|^3", - "symfony/stopwatch": "^4.4|^5.0|^6.0" - }, - "suggest": { - "symfony/dependency-injection": "", - "symfony/http-kernel": "" - }, - "type": "library", - "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": "Provides tools that allow your application components to communicate with each other by dispatching events and listening to them", - "homepage": "https://symfony.com", - "support": { - "source": "https://github.com/symfony/event-dispatcher/tree/v5.4.26" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2023-07-06T06:34:20+00:00" - }, - { - "name": "symfony/event-dispatcher-contracts", - "version": "v2.5.2", - "source": { - "type": "git", - "url": "https://github.com/symfony/event-dispatcher-contracts.git", - "reference": "f98b54df6ad059855739db6fcbc2d36995283fe1" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/event-dispatcher-contracts/zipball/f98b54df6ad059855739db6fcbc2d36995283fe1", - "reference": "f98b54df6ad059855739db6fcbc2d36995283fe1", - "shasum": "" - }, - "require": { - "php": ">=7.2.5", - "psr/event-dispatcher": "^1" - }, - "suggest": { - "symfony/event-dispatcher-implementation": "" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "2.5-dev" - }, - "thanks": { - "name": "symfony/contracts", - "url": "https://github.com/symfony/contracts" - } - }, - "autoload": { - "psr-4": { - "Symfony\\Contracts\\EventDispatcher\\": "" - } - }, - "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": "Generic abstractions related to dispatching event", - "homepage": "https://symfony.com", - "keywords": [ - "abstractions", - "contracts", - "decoupling", - "interfaces", - "interoperability", - "standards" - ], - "support": { - "source": "https://github.com/symfony/event-dispatcher-contracts/tree/v2.5.2" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2022-01-02T09:53:40+00:00" - }, - { - "name": "symfony/filesystem", - "version": "v5.4.25", - "source": { - "type": "git", - "url": "https://github.com/symfony/filesystem.git", - "reference": "0ce3a62c9579a53358d3a7eb6b3dfb79789a6364" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/filesystem/zipball/0ce3a62c9579a53358d3a7eb6b3dfb79789a6364", - "reference": "0ce3a62c9579a53358d3a7eb6b3dfb79789a6364", - "shasum": "" - }, - "require": { - "php": ">=7.2.5", - "symfony/polyfill-ctype": "~1.8", - "symfony/polyfill-mbstring": "~1.8", - "symfony/polyfill-php80": "^1.16" - }, - "type": "library", - "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": "Provides basic utilities for the filesystem", - "homepage": "https://symfony.com", - "support": { - "source": "https://github.com/symfony/filesystem/tree/v5.4.25" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2023-05-31T13:04:02+00:00" - }, - { - "name": "symfony/finder", - "version": "v5.4.27", - "source": { - "type": "git", - "url": "https://github.com/symfony/finder.git", - "reference": "ff4bce3c33451e7ec778070e45bd23f74214cd5d" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/finder/zipball/ff4bce3c33451e7ec778070e45bd23f74214cd5d", - "reference": "ff4bce3c33451e7ec778070e45bd23f74214cd5d", - "shasum": "" - }, - "require": { - "php": ">=7.2.5", - "symfony/deprecation-contracts": "^2.1|^3", - "symfony/polyfill-php80": "^1.16" - }, - "type": "library", - "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": "Finds files and directories via an intuitive fluent interface", - "homepage": "https://symfony.com", - "support": { - "source": "https://github.com/symfony/finder/tree/v5.4.27" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2023-07-31T08:02:31+00:00" - }, - { - "name": "symfony/options-resolver", - "version": "v5.4.21", - "source": { - "type": "git", - "url": "https://github.com/symfony/options-resolver.git", - "reference": "4fe5cf6ede71096839f0e4b4444d65dd3a7c1eb9" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/options-resolver/zipball/4fe5cf6ede71096839f0e4b4444d65dd3a7c1eb9", - "reference": "4fe5cf6ede71096839f0e4b4444d65dd3a7c1eb9", - "shasum": "" - }, - "require": { - "php": ">=7.2.5", - "symfony/deprecation-contracts": "^2.1|^3", - "symfony/polyfill-php73": "~1.0", - "symfony/polyfill-php80": "^1.16" - }, - "type": "library", - "autoload": { - "psr-4": { - "Symfony\\Component\\OptionsResolver\\": "" - }, - "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": "Provides an improved replacement for the array_replace PHP function", - "homepage": "https://symfony.com", - "keywords": [ - "config", - "configuration", - "options" - ], - "support": { - "source": "https://github.com/symfony/options-resolver/tree/v5.4.21" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2023-02-14T08:03:56+00:00" - }, - { - "name": "symfony/polyfill-ctype", - "version": "v1.28.0", - "source": { - "type": "git", - "url": "https://github.com/symfony/polyfill-ctype.git", - "reference": "ea208ce43cbb04af6867b4fdddb1bdbf84cc28cb" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/ea208ce43cbb04af6867b4fdddb1bdbf84cc28cb", - "reference": "ea208ce43cbb04af6867b4fdddb1bdbf84cc28cb", - "shasum": "" - }, - "require": { - "php": ">=7.1" - }, - "provide": { - "ext-ctype": "*" - }, - "suggest": { - "ext-ctype": "For best performance" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "1.28-dev" - }, - "thanks": { - "name": "symfony/polyfill", - "url": "https://github.com/symfony/polyfill" - } - }, - "autoload": { - "files": [ - "bootstrap.php" - ], - "psr-4": { - "Symfony\\Polyfill\\Ctype\\": "" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Gert de Pagter", - "email": "BackEndTea@gmail.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Symfony polyfill for ctype functions", - "homepage": "https://symfony.com", - "keywords": [ - "compatibility", - "ctype", - "polyfill", - "portable" - ], - "support": { - "source": "https://github.com/symfony/polyfill-ctype/tree/v1.28.0" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2023-01-26T09:26:14+00:00" - }, - { - "name": "symfony/polyfill-intl-grapheme", - "version": "v1.28.0", - "source": { - "type": "git", - "url": "https://github.com/symfony/polyfill-intl-grapheme.git", - "reference": "875e90aeea2777b6f135677f618529449334a612" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-intl-grapheme/zipball/875e90aeea2777b6f135677f618529449334a612", - "reference": "875e90aeea2777b6f135677f618529449334a612", - "shasum": "" - }, - "require": { - "php": ">=7.1" - }, - "suggest": { - "ext-intl": "For best performance" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "1.28-dev" - }, - "thanks": { - "name": "symfony/polyfill", - "url": "https://github.com/symfony/polyfill" - } - }, - "autoload": { - "files": [ - "bootstrap.php" - ], - "psr-4": { - "Symfony\\Polyfill\\Intl\\Grapheme\\": "" - } - }, - "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 intl's grapheme_* functions", - "homepage": "https://symfony.com", - "keywords": [ - "compatibility", - "grapheme", - "intl", - "polyfill", - "portable", - "shim" - ], - "support": { - "source": "https://github.com/symfony/polyfill-intl-grapheme/tree/v1.28.0" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2023-01-26T09:26:14+00:00" - }, - { - "name": "symfony/polyfill-mbstring", - "version": "v1.28.0", - "source": { - "type": "git", - "url": "https://github.com/symfony/polyfill-mbstring.git", - "reference": "42292d99c55abe617799667f454222c54c60e229" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/42292d99c55abe617799667f454222c54c60e229", - "reference": "42292d99c55abe617799667f454222c54c60e229", - "shasum": "" - }, - "require": { - "php": ">=7.1" - }, - "provide": { - "ext-mbstring": "*" - }, - "suggest": { - "ext-mbstring": "For best performance" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "1.28-dev" - }, - "thanks": { - "name": "symfony/polyfill", - "url": "https://github.com/symfony/polyfill" - } - }, - "autoload": { - "files": [ - "bootstrap.php" - ], - "psr-4": { - "Symfony\\Polyfill\\Mbstring\\": "" - } - }, - "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" - ], - "support": { - "source": "https://github.com/symfony/polyfill-mbstring/tree/v1.28.0" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2023-07-28T09:04:16+00:00" - }, - { - "name": "symfony/polyfill-php73", - "version": "v1.28.0", - "source": { - "type": "git", - "url": "https://github.com/symfony/polyfill-php73.git", - "reference": "fe2f306d1d9d346a7fee353d0d5012e401e984b5" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-php73/zipball/fe2f306d1d9d346a7fee353d0d5012e401e984b5", - "reference": "fe2f306d1d9d346a7fee353d0d5012e401e984b5", - "shasum": "" - }, - "require": { - "php": ">=7.1" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "1.28-dev" - }, - "thanks": { - "name": "symfony/polyfill", - "url": "https://github.com/symfony/polyfill" - } - }, - "autoload": { - "files": [ - "bootstrap.php" - ], - "psr-4": { - "Symfony\\Polyfill\\Php73\\": "" - }, - "classmap": [ - "Resources/stubs" - ] - }, - "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 backporting some PHP 7.3+ features to lower PHP versions", - "homepage": "https://symfony.com", - "keywords": [ - "compatibility", - "polyfill", - "portable", - "shim" - ], - "support": { - "source": "https://github.com/symfony/polyfill-php73/tree/v1.28.0" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2023-01-26T09:26:14+00:00" - }, - { - "name": "symfony/polyfill-php80", - "version": "v1.31.0", - "source": { - "type": "git", - "url": "https://github.com/symfony/polyfill-php80.git", - "reference": "60328e362d4c2c802a54fcbf04f9d3fb892b4cf8" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-php80/zipball/60328e362d4c2c802a54fcbf04f9d3fb892b4cf8", - "reference": "60328e362d4c2c802a54fcbf04f9d3fb892b4cf8", - "shasum": "" - }, - "require": { - "php": ">=7.2" - }, - "type": "library", - "extra": { - "thanks": { - "url": "https://github.com/symfony/polyfill", - "name": "symfony/polyfill" - } - }, - "autoload": { - "files": [ - "bootstrap.php" - ], - "psr-4": { - "Symfony\\Polyfill\\Php80\\": "" - }, - "classmap": [ - "Resources/stubs" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Ion Bazan", - "email": "ion.bazan@gmail.com" - }, - { - "name": "Nicolas Grekas", - "email": "p@tchwork.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Symfony polyfill backporting some PHP 8.0+ features to lower PHP versions", - "homepage": "https://symfony.com", - "keywords": [ - "compatibility", - "polyfill", - "portable", - "shim" - ], - "support": { - "source": "https://github.com/symfony/polyfill-php80/tree/v1.31.0" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2024-09-09T11:45:10+00:00" - }, - { - "name": "symfony/polyfill-php81", - "version": "v1.28.0", - "source": { - "type": "git", - "url": "https://github.com/symfony/polyfill-php81.git", - "reference": "7581cd600fa9fd681b797d00b02f068e2f13263b" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-php81/zipball/7581cd600fa9fd681b797d00b02f068e2f13263b", - "reference": "7581cd600fa9fd681b797d00b02f068e2f13263b", - "shasum": "" - }, - "require": { - "php": ">=7.1" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "1.28-dev" - }, - "thanks": { - "name": "symfony/polyfill", - "url": "https://github.com/symfony/polyfill" - } - }, - "autoload": { - "files": [ - "bootstrap.php" - ], - "psr-4": { - "Symfony\\Polyfill\\Php81\\": "" - }, - "classmap": [ - "Resources/stubs" - ] - }, - "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 backporting some PHP 8.1+ features to lower PHP versions", - "homepage": "https://symfony.com", - "keywords": [ - "compatibility", - "polyfill", - "portable", - "shim" - ], - "support": { - "source": "https://github.com/symfony/polyfill-php81/tree/v1.28.0" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2023-01-26T09:26:14+00:00" - }, - { - "name": "symfony/process", - "version": "v5.4.47", - "source": { - "type": "git", - "url": "https://github.com/symfony/process.git", - "reference": "5d1662fb32ebc94f17ddb8d635454a776066733d" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/process/zipball/5d1662fb32ebc94f17ddb8d635454a776066733d", - "reference": "5d1662fb32ebc94f17ddb8d635454a776066733d", - "shasum": "" - }, - "require": { - "php": ">=7.2.5", - "symfony/polyfill-php80": "^1.16" - }, - "type": "library", - "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": "Executes commands in sub-processes", - "homepage": "https://symfony.com", - "support": { - "source": "https://github.com/symfony/process/tree/v5.4.47" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2024-11-06T11:36:42+00:00" - }, - { - "name": "symfony/service-contracts", - "version": "v2.5.2", - "source": { - "type": "git", - "url": "https://github.com/symfony/service-contracts.git", - "reference": "4b426aac47d6427cc1a1d0f7e2ac724627f5966c" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/service-contracts/zipball/4b426aac47d6427cc1a1d0f7e2ac724627f5966c", - "reference": "4b426aac47d6427cc1a1d0f7e2ac724627f5966c", - "shasum": "" - }, - "require": { - "php": ">=7.2.5", - "psr/container": "^1.1", - "symfony/deprecation-contracts": "^2.1|^3" - }, - "conflict": { - "ext-psr": "<1.1|>=2" - }, - "suggest": { - "symfony/service-implementation": "" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "2.5-dev" - }, - "thanks": { - "name": "symfony/contracts", - "url": "https://github.com/symfony/contracts" - } - }, - "autoload": { - "psr-4": { - "Symfony\\Contracts\\Service\\": "" - } - }, - "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": "Generic abstractions related to writing services", - "homepage": "https://symfony.com", - "keywords": [ - "abstractions", - "contracts", - "decoupling", - "interfaces", - "interoperability", - "standards" - ], - "support": { - "source": "https://github.com/symfony/service-contracts/tree/v2.5.2" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2022-05-30T19:17:29+00:00" - }, - { - "name": "symfony/stopwatch", - "version": "v5.4.21", - "source": { - "type": "git", - "url": "https://github.com/symfony/stopwatch.git", - "reference": "f83692cd869a6f2391691d40a01e8acb89e76fee" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/stopwatch/zipball/f83692cd869a6f2391691d40a01e8acb89e76fee", - "reference": "f83692cd869a6f2391691d40a01e8acb89e76fee", - "shasum": "" - }, - "require": { - "php": ">=7.2.5", - "symfony/service-contracts": "^1|^2|^3" - }, - "type": "library", - "autoload": { - "psr-4": { - "Symfony\\Component\\Stopwatch\\": "" - }, - "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": "Provides a way to profile code", - "homepage": "https://symfony.com", - "support": { - "source": "https://github.com/symfony/stopwatch/tree/v5.4.21" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2023-02-14T08:03:56+00:00" - }, - { - "name": "symfony/string", - "version": "v5.4.26", - "source": { - "type": "git", - "url": "https://github.com/symfony/string.git", - "reference": "1181fe9270e373537475e826873b5867b863883c" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/string/zipball/1181fe9270e373537475e826873b5867b863883c", - "reference": "1181fe9270e373537475e826873b5867b863883c", - "shasum": "" - }, - "require": { - "php": ">=7.2.5", - "symfony/polyfill-ctype": "~1.8", - "symfony/polyfill-intl-grapheme": "~1.0", - "symfony/polyfill-intl-normalizer": "~1.0", - "symfony/polyfill-mbstring": "~1.0", - "symfony/polyfill-php80": "~1.15" - }, - "conflict": { - "symfony/translation-contracts": ">=3.0" - }, - "require-dev": { - "symfony/error-handler": "^4.4|^5.0|^6.0", - "symfony/http-client": "^4.4|^5.0|^6.0", - "symfony/translation-contracts": "^1.1|^2", - "symfony/var-exporter": "^4.4|^5.0|^6.0" - }, - "type": "library", - "autoload": { - "files": [ - "Resources/functions.php" - ], - "psr-4": { - "Symfony\\Component\\String\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "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": "Provides an object-oriented API to strings and deals with bytes, UTF-8 code points and grapheme clusters in a unified way", - "homepage": "https://symfony.com", - "keywords": [ - "grapheme", - "i18n", - "string", - "unicode", - "utf-8", - "utf8" - ], - "support": { - "source": "https://github.com/symfony/string/tree/v5.4.26" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2023-06-28T12:46:07+00:00" - }, - { - "name": "theseer/tokenizer", - "version": "1.2.1", - "source": { - "type": "git", - "url": "https://github.com/theseer/tokenizer.git", - "reference": "34a41e998c2183e22995f158c581e7b5e755ab9e" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/theseer/tokenizer/zipball/34a41e998c2183e22995f158c581e7b5e755ab9e", - "reference": "34a41e998c2183e22995f158c581e7b5e755ab9e", - "shasum": "" - }, - "require": { - "ext-dom": "*", - "ext-tokenizer": "*", - "ext-xmlwriter": "*", - "php": "^7.2 || ^8.0" - }, - "type": "library", - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Arne Blankerts", - "email": "arne@blankerts.de", - "role": "Developer" - } - ], - "description": "A small library for converting tokenized PHP source code into XML and potentially other formats", - "support": { - "issues": "https://github.com/theseer/tokenizer/issues", - "source": "https://github.com/theseer/tokenizer/tree/1.2.1" - }, - "funding": [ - { - "url": "https://github.com/theseer", - "type": "github" - } - ], - "time": "2021-07-28T10:34:58+00:00" - }, - { - "name": "vimeo/psalm", - "version": "5.15.0", - "source": { - "type": "git", - "url": "https://github.com/vimeo/psalm.git", - "reference": "5c774aca4746caf3d239d9c8cadb9f882ca29352" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/vimeo/psalm/zipball/5c774aca4746caf3d239d9c8cadb9f882ca29352", - "reference": "5c774aca4746caf3d239d9c8cadb9f882ca29352", - "shasum": "" - }, - "require": { - "amphp/amp": "^2.4.2", - "amphp/byte-stream": "^1.5", - "composer-runtime-api": "^2", - "composer/semver": "^1.4 || ^2.0 || ^3.0", - "composer/xdebug-handler": "^2.0 || ^3.0", - "dnoegel/php-xdg-base-dir": "^0.1.1", - "ext-ctype": "*", - "ext-dom": "*", - "ext-json": "*", - "ext-libxml": "*", - "ext-mbstring": "*", - "ext-simplexml": "*", - "ext-tokenizer": "*", - "felixfbecker/advanced-json-rpc": "^3.1", - "felixfbecker/language-server-protocol": "^1.5.2", - "fidry/cpu-core-counter": "^0.4.1 || ^0.5.1", - "netresearch/jsonmapper": "^1.0 || ^2.0 || ^3.0 || ^4.0", - "nikic/php-parser": "^4.16", - "php": "^7.4 || ~8.0.0 || ~8.1.0 || ~8.2.0 || ~8.3.0", - "sebastian/diff": "^4.0 || ^5.0", - "spatie/array-to-xml": "^2.17.0 || ^3.0", - "symfony/console": "^4.1.6 || ^5.0 || ^6.0", - "symfony/filesystem": "^5.4 || ^6.0" - }, - "conflict": { - "nikic/php-parser": "4.17.0" - }, - "provide": { - "psalm/psalm": "self.version" - }, - "require-dev": { - "amphp/phpunit-util": "^2.0", - "bamarni/composer-bin-plugin": "^1.4", - "brianium/paratest": "^6.9", - "ext-curl": "*", - "mockery/mockery": "^1.5", - "nunomaduro/mock-final-classes": "^1.1", - "php-parallel-lint/php-parallel-lint": "^1.2", - "phpstan/phpdoc-parser": "^1.6", - "phpunit/phpunit": "^9.6", - "psalm/plugin-mockery": "^1.1", - "psalm/plugin-phpunit": "^0.18", - "slevomat/coding-standard": "^8.4", - "squizlabs/php_codesniffer": "^3.6", - "symfony/process": "^4.4 || ^5.0 || ^6.0" - }, - "suggest": { - "ext-curl": "In order to send data to shepherd", - "ext-igbinary": "^2.0.5 is required, used to serialize caching data" - }, - "bin": [ - "psalm", - "psalm-language-server", - "psalm-plugin", - "psalm-refactor", - "psalter" - ], - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "5.x-dev", - "dev-4.x": "4.x-dev", - "dev-3.x": "3.x-dev", - "dev-2.x": "2.x-dev", - "dev-1.x": "1.x-dev" - } - }, - "autoload": { - "psr-4": { - "Psalm\\": "src/Psalm/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Matthew Brown" - } - ], - "description": "A static analysis tool for finding errors in PHP applications", - "keywords": [ - "code", - "inspection", - "php", - "static analysis" - ], - "support": { - "issues": "https://github.com/vimeo/psalm/issues", - "source": "https://github.com/vimeo/psalm/tree/5.15.0" - }, - "time": "2023-08-20T23:07:30+00:00" - }, - { - "name": "webmozart/assert", - "version": "1.11.0", - "source": { - "type": "git", - "url": "https://github.com/webmozarts/assert.git", - "reference": "11cb2199493b2f8a3b53e7f19068fc6aac760991" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/webmozarts/assert/zipball/11cb2199493b2f8a3b53e7f19068fc6aac760991", - "reference": "11cb2199493b2f8a3b53e7f19068fc6aac760991", - "shasum": "" - }, - "require": { - "ext-ctype": "*", - "php": "^7.2 || ^8.0" - }, - "conflict": { - "phpstan/phpstan": "<0.12.20", - "vimeo/psalm": "<4.6.1 || 4.6.2" - }, - "require-dev": { - "phpunit/phpunit": "^8.5.13" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.10-dev" - } - }, - "autoload": { - "psr-4": { - "Webmozart\\Assert\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Bernhard Schussek", - "email": "bschussek@gmail.com" - } - ], - "description": "Assertions to validate method input/output with nice error messages.", - "keywords": [ - "assert", - "check", - "validate" - ], - "support": { - "issues": "https://github.com/webmozarts/assert/issues", - "source": "https://github.com/webmozarts/assert/tree/1.11.0" - }, - "time": "2022-06-03T18:03:27+00:00" - } - ], - "aliases": [], - "minimum-stability": "stable", - "stability-flags": [], - "prefer-stable": false, - "prefer-lowest": false, - "platform": { - "php": "^7.4||^8.0" - }, - "platform-dev": [], - "platform-overrides": { - "php": "7.4" - }, - "plugin-api-version": "2.6.0" -} diff --git a/docs/architecture/decisions/0001-record-architecture-decisions.md b/docs/architecture/decisions/0001-record-architecture-decisions.md new file mode 100644 index 00000000..de4dfe06 --- /dev/null +++ b/docs/architecture/decisions/0001-record-architecture-decisions.md @@ -0,0 +1,19 @@ +# 1. Record architecture decisions + +Date: 2025-04-22 + +## Status + +Accepted + +## Context + +We need to record the architectural decisions made on this project. + +## Decision + +We will use Architecture Decision Records, as [described by Michael Nygard](http://thinkrelevance.com/blog/2011/11/15/documenting-architecture-decisions). + +## Consequences + +See Michael Nygard's article, linked above. For a lightweight ADR toolset, see Nat Pryce's [adr-tools](https://github.com/npryce/adr-tools). diff --git a/docs/architecture/decisions/0002-use-rust-for-development.md b/docs/architecture/decisions/0002-use-rust-for-development.md new file mode 100644 index 00000000..64403d71 --- /dev/null +++ b/docs/architecture/decisions/0002-use-rust-for-development.md @@ -0,0 +1,42 @@ +# 2. Use Rust for development + +Date: 2025-04-22 + +## Status + +Accepted + +## Context + +Previous versions of Whippet were written in PHP, which is not well suited +to desktop CLI apps. Moreover, Whippet has variously been a server a local +development environment and various other sorts of tooling. The accretion of +code over the years has led to a mis-match in coding styles and architectural +decisions and, most noticeably, the use of several different testing frameworks. +This has meant that it is difficult to add significant new features or to +refactor the code we already have. + +This means that the cost of re-engineering the application from scratch is not +likely to be much more expensive than refactoring the code we have. + +Rust is a reasonable choice for a new Whippet for the following reasons: + +1. Rust is type safe, memory safe and has strong tooling for linting, formatting + and a built in testing library. +2. Rust is _fast_. It is a compiled language and binaries are portable, so can + be used on MacOS and also Ubuntu (which we use for CI pipelines) without + cross-compiling. +3. It is relatively easy to use threads in Rust, which we would like to try + in order to run I/O operations such as Git clones or checkouts, in parallel. + +## Decision + +We will use Rust for a first attempt at re-writing Whippet and review the choice +once 'whippet deps update' has been implemented, so that we can run Whippet v2 +and v3 side-by-side and compare them. + +## Consequences + +Both the tooling and the Whippet app will need replacing. The re-written Whippet +will be safer, changes will be easier to make but there will be a steep learning +curve for anyone working on this repository, which may slow down development. diff --git a/generators/app/generate.php b/generators/app/generate.php deleted file mode 100644 index b264f470..00000000 --- a/generators/app/generate.php +++ /dev/null @@ -1,85 +0,0 @@ -options = $options; - - if(isset($this->options->directory)) { - $this->target_dir = $this->options->directory; - } - else { - $this->target_dir = getcwd() . "/whippet-app"; - } - } - - - function generate() { - echo "Creating a new whippet application in {$this->target_dir}\n"; - - if(!file_exists($this->target_dir)) { - mkdir($this->target_dir); - } - - // Make the target dir a git repo, if it isn't already - $target_repo = new \Dxw\Whippet\Git\Git($this->target_dir); - if(!$target_repo->is_repo()) { - \Dxw\Whippet\Git\Git::init($this->target_dir); - } - - echo "Downloading and unzipping template file \n"; - - $this->downloadTemplateZip(); - - $this->unzipAndRemoveTemplateZip(); - - if(isset($this->options->repository)) { - $this->setWPRepository(); - } - - /* zip archives don't preserve permissions, so fix those */ - exec("chmod 0755 " . $this->target_dir . "/setup/*"); - exec("chmod 0755 " . $this->target_dir . "/script/*"); - exec("chmod 0755 " . $this->target_dir . "/bin/*"); - - // Whippet deploy requires at least one commit in the repo. - if (!$target_repo->current_commit()) { - $target_repo->add("--all"); - $target_repo->commit("Initial commit from Whippet"); - } - - echo "New whippet app successfully generated at {$this->target_dir} \n"; - } - - private function setWpRepository() - { - $appConfig = $this->target_dir . '/config/application.json'; - $data = json_decode(file_get_contents($appConfig), JSON_OBJECT_AS_ARRAY); - $data['wordpress']['repository'] = $this->options->repository; - file_put_contents($appConfig, json_encode($data, JSON_PRETTY_PRINT|JSON_UNESCAPED_SLASHES)."\n"); - } - - private function getLatest() - { - $versionCheck = json_decode(file_get_contents('https://api.wordpress.org/core/version-check/1.7/'), JSON_OBJECT_AS_ARRAY); - return $versionCheck['offers'][0]['version']; - } - - private function downloadTemplateZip() - { - $this->download_url_to_file($this->wordpress_template_zip, $this->target_dir . "/wordpress_template.zip"); - } - - private function unzipAndRemoveTemplateZip() - { - $this->unzip_to_folder($this->target_dir . "/wordpress_template.zip", $this->target_dir); - // Move the unzipped contents out of the containing zip folder - $this->recurse_copy($this->target_dir . '/wordpress-template-main', $this->target_dir); - $this->recurse_rm($this->target_dir . '/wordpress-template-main'); - } -}; diff --git a/generators/plugin/generate.php b/generators/plugin/generate.php deleted file mode 100644 index 3e2ba45f..00000000 --- a/generators/plugin/generate.php +++ /dev/null @@ -1,53 +0,0 @@ -options = $options; - - if(isset($this->options->directory)) { - $this->target_dir = getcwd() . '/' . $this->options->directory; - } - else { - $this->target_dir = getcwd() . "/whippet-plugin"; - } - - $this->unique_temp_id = uniqid(); - } - - function generate() { - echo "Creating a new whippet plugin in {$this->target_dir}\n"; - - if(!file_exists($this->target_dir)) { - mkdir($this->target_dir); - } - - $this->downloadAndUnzipTemplate(); - $this->copyThemeAndRemoveTemplate(); - } - - private function downloadAndUnzipTemplate() - { - $this->download_url_to_file($this->plugin_template_zip, '/tmp/plugin_template_' . $this->unique_temp_id . '.zip'); - $this->unzip_to_folder('/tmp/plugin_template_' . $this->unique_temp_id . '.zip', '/tmp/plugin_template_' . $this->unique_temp_id); - } - - private function copyThemeAndRemoveTemplate() - { - $this->recurse_copy('/tmp/plugin_template_' . $this->unique_temp_id . '/wordpress-plugin-template-main', $this->target_dir); - copy('/tmp/plugin_template_' . $this->unique_temp_id . '/wordpress-plugin-template-main/.gitignore', $this->target_dir . '/.gitignore'); - if(isset($this->options->nogitignore)) { - unlink($this->target_dir . '/.gitignore'); - } - $this->recurse_rm('/tmp/plugin_template_' . $this->unique_temp_id); - } -}; diff --git a/generators/theme/generate.php b/generators/theme/generate.php deleted file mode 100644 index d87cc127..00000000 --- a/generators/theme/generate.php +++ /dev/null @@ -1,53 +0,0 @@ -options = $options; - - if(isset($this->options->directory)) { - $this->target_dir = getcwd() . '/' . $this->options->directory; - } - else { - $this->target_dir = getcwd() . "/whippet-theme"; - } - - $this->unique_temp_id = uniqid(); - } - - function generate() { - echo "Creating a new whippet theme in {$this->target_dir}\n"; - - if(!file_exists($this->target_dir)) { - mkdir($this->target_dir); - } - - $this->downloadAndUnzipTemplate(); - $this->copyThemeAndRemoveTemplate(); - } - - private function downloadAndUnzipTemplate() - { - $this->download_url_to_file($this->wordpress_template_zip, '/tmp/wordpress_template_' . $this->unique_temp_id . '.zip'); - $this->unzip_to_folder('/tmp/wordpress_template_' . $this->unique_temp_id . '.zip', '/tmp/wordpress_template_' . $this->unique_temp_id); - } - - private function copyThemeAndRemoveTemplate() - { - $this->recurse_copy('/tmp/wordpress_template_' . $this->unique_temp_id . '/wordpress-template-main/wp-content/themes/theme', $this->target_dir); - copy('/tmp/wordpress_template_' . $this->unique_temp_id . '/wordpress-template-main/.gitignore', $this->target_dir . '/.gitignore'); - if(isset($this->options->nogitignore)) { - unlink($this->target_dir . '/.gitignore'); - } - $this->recurse_rm('/tmp/wordpress_template_' . $this->unique_temp_id); - } -}; diff --git a/phpunit.xml b/phpunit.xml deleted file mode 100644 index 1e261426..00000000 --- a/phpunit.xml +++ /dev/null @@ -1,13 +0,0 @@ - - - - - src - - - - - tests - - - diff --git a/psalm.xml b/psalm.xml deleted file mode 100644 index d72d164c..00000000 --- a/psalm.xml +++ /dev/null @@ -1,20 +0,0 @@ - - - - - - - - - - - - diff --git a/script/bootstrap b/script/bootstrap index 0abe14b7..b1ec90cf 100755 --- a/script/bootstrap +++ b/script/bootstrap @@ -16,7 +16,5 @@ if [ -z "$CI" ]; then fi fi -if [ -f composer.json ]; then - echo "==> Installing PHP dependencies using Composer..." - composer install -fi +echo "==> Updating Cargo dependencies..." +cargo update diff --git a/script/build b/script/build new file mode 100755 index 00000000..82e1ca2f --- /dev/null +++ b/script/build @@ -0,0 +1,20 @@ +#!/bin/sh + +# script/test: Build the application. + +set -e + +cd "$(dirname "$0")/.." + +if [ -n "$DEBUG" ]; then + set -x +fi + +echo "==> Updating..." +script/update + +echo "==> Cleaning old files..." +cargo clean + +echo "==> Building Whippet..." +cargo build diff --git a/script/test b/script/test index a0cbf2b4..0111dea6 100755 --- a/script/test +++ b/script/test @@ -11,24 +11,17 @@ if [ -n "$DEBUG" ]; then set -x fi -echo "==> Updating..." -script/update +echo "==> Building..." +script/build -TEST_FILE=$1 +echo "==> Running ShellCheck..." +./.shellcheck.sh -if [ -n "$TEST_FILE" ]; then - echo "==> Running the tests matching '$TEST_FILE'..." - ./vendor/bin/phpunit "$TEST_FILE" -else - echo "==> Running ShellCheck..." - ./.shellcheck.sh +echo "==> Running code formatter..." +cargo fmt - echo "==> Running php-cs-fixer..." - ./vendor/bin/php-cs-fixer fix --dry-run -v --diff +echo "==> Running code linter..." +cargo clippy - echo "==> Running Psalm..." - ./vendor/bin/psalm - - echo "==> Running the tests..." - ./vendor/bin/phpunit && ./vendor/bin/kahlan spec -fi +echo "==> Running the tests..." +cargo test diff --git a/spec/dependencies/dependency_types.spec.php b/spec/dependencies/dependency_types.spec.php deleted file mode 100644 index 1aae91d7..00000000 --- a/spec/dependencies/dependency_types.spec.php +++ /dev/null @@ -1,9 +0,0 @@ -toBe(['themes', 'plugins']); - }); - }); -}); diff --git a/spec/dependencies/describer.spec.php b/spec/dependencies/describer.spec.php deleted file mode 100644 index b715075e..00000000 --- a/spec/dependencies/describer.spec.php +++ /dev/null @@ -1,101 +0,0 @@ -factory = Double::instance(['extends' => '\Dxw\Whippet\Factory']); - $this->projectDirectory = Double::instance([ - 'extends' => 'Dxw\Whippet\ProjectDirectory', - 'magicMethods' => true - ]); - $this->describer = new \Dxw\Whippet\Dependencies\Describer( - $this->factory, - $this->projectDirectory - ); - }); - - describe('->describe()', function () { - context('whippet.lock file not loaded successfully', function () { - it('returns an error result', function () { - allow($this->factory)->toReceive('callStatic')->andReturn(\Result\Result::err('Error loading whippet.lock')); - - $result = $this->describer->describe(); - - expect($result->isErr())->toEqual(true); - expect($result->getErr())->toEqual('Error loading whippet.lock'); - }); - }); - - context('Error getting the references for one of the git repos', function () { - it('returns an error result', function () { - $whippetLock = Double::instance([ - 'extends' => '\Dxw\Whippet\Files\WhippetLock', - 'magicMethods' => true - ]); - allow($whippetLock)->toReceive('getDependencies')->andReturn([ - [ - 'name' => 'plugin-one', - 'src' => 'plugin-one-src', - 'revision' => 'commit-hash' - ] - ]); - allow($this->factory)->toReceive('callStatic')->andReturn(\Result\Result::ok($whippetLock)); - $git = Double::instance([ - 'extends' => '\Dxw\Whippet\Git\Git', - 'magicMethods' => true - ]); - allow(\Dxw\Whippet\Git\Git::class)->toBe($git); - allow($git)->toReceive('::tag_for_commit')->andReturn(\Result\Result::err('Error getting tag')); - - $result = $this->describer->describe(); - - expect($result->isErr())->toEqual(true); - expect($result->getErr())->toEqual('Error getting tag'); - }); - }); - - it('outputs a JSON report and returns an OK result', function () { - $whippetLock = Double::instance([ - 'extends' => '\Dxw\Whippet\Files\WhippetLock', - 'magicMethods' => true - ]); - allow($whippetLock)->toReceive('getDependencies')->andReturn([ - [ - 'name' => 'theme-one', - 'src' => 'theme-one-src', - 'revision' => 'commit-hash' - ] - ], [ - [ - 'name' => 'plugin-one', - 'src' => 'plugin-one-src', - 'revision' => 'commit-hash' - ], - ]); - allow($this->factory)->toReceive('callStatic')->andReturn(\Result\Result::ok($whippetLock)); - $git = Double::instance([ - 'extends' => '\Dxw\Whippet\Git\Git', - 'magicMethods' => true - ]); - allow(\Dxw\Whippet\Git\Git::class)->toBe($git); - allow($git)->toReceive('::tag_for_commit')->andReturn(\Result\Result::ok('v1.0.1'), \Result\Result::ok('v3.0')); - - ob_start(); - - $result = $this->describer->describe(); - - $output = ob_get_clean(); - - expect(json_decode($output, null, 5, JSON_OBJECT_AS_ARRAY))->toEqual([ - 'themes' => [ - 'theme-one' => 'v1.0.1' - ], - 'plugins' => [ - 'plugin-one' => 'v3.0' - ] - ]); - expect($result->isErr())->toBe(false); - }); - }); -}); diff --git a/spec/dependencies/validator.spec.php b/spec/dependencies/validator.spec.php deleted file mode 100644 index da838bf3..00000000 --- a/spec/dependencies/validator.spec.php +++ /dev/null @@ -1,317 +0,0 @@ -factory = Double::instance(['extends' => '\Dxw\Whippet\Factory']); - $this->projectDirectory = Double::instance([ - 'extends' => 'Dxw\Whippet\ProjectDirectory', - 'magicMethods' => true - ]); - $this->validator = new \Dxw\Whippet\Dependencies\Validator( - $this->factory, - $this->projectDirectory - ); - }); - - describe('->validate()', function () { - context('whippet.lock cannot be found, or is invalid JSON', function () { - it('returns an error', function () { - allow($this->factory)->toReceive('callStatic')->andReturn(\Result\Result::err('An error')); - $result = $this->validator->validate(); - expect($result)->toBeAnInstanceOf(\Result\Result::class); - expect($result->getErr())->toEqual('whippet.lock error: An error'); - }); - }); - - context('whippet.json cannot be found, or is invalid JSON', function () { - it('returns an error', function () { - $this->whippetLock = Double::instance(); - allow($this->whippetLock)->toReceive('isErr')->andReturn(false); - allow($this->whippetLock)->toReceive('unwrap')->andReturn($this->whippetLock); - allow($this->factory)->toReceive('callStatic')->andReturn( - $this->whippetLock, - \Result\Result::err('Whippet Json error') - ); - $result = $this->validator->validate(); - expect($result)->toBeAnInstanceOf(\Result\Result::class); - expect($result->getErr())->toEqual('whippet.json error: Whippet Json error'); - }); - }); - - context('both whippet.json and whippet.lock are present and valid', function () { - beforeEach(function () { - $this->whippetLock = Double::instance(); - allow($this->whippetLock)->toReceive('isErr')->andReturn(false); - allow($this->whippetLock)->toReceive('unwrap')->andReturn($this->whippetLock); - $this->whippetJson = Double::instance(); - allow($this->whippetJson)->toReceive('isErr')->andReturn(false); - allow($this->whippetJson)->toReceive('unwrap')->andReturn($this->whippetJson); - allow($this->factory)->toReceive('callStatic')->andReturn( - $this->whippetLock, - $this->whippetJson - ); - }); - context('but the hash is mismatched', function () { - it('returns an error', function () { - $whippetContents = '{ - "src": { - "plugins": "git@github.com:dxw-wordpress-plugins/" - }, - "plugins": [ - {"name": "akismet"}, - {"name": "advanced-custom-fields-pro"} - ] - }'; - allow('file_get_contents')->toBeCalled()->andReturn($whippetContents); - allow('sha1')->toBeCalled()->andReturn('a_sha'); - expect('sha1')->toBeCalled()->once()->with($whippetContents); - allow($this->whippetLock)->toReceive('getHash')->andReturn('a_different_sha'); - $result = $this->validator->validate(); - expect($result)->toBeAnInstanceOf(\Result\Result::class); - expect($result->getErr())->toEqual('hash mismatch between whippet.json and whippet.lock'); - }); - }); - context('but there are different numbers of dependencies in the .json and .lock', function () { - it('returns an error', function () { - $whippetContents = '{ - "src": { - "plugins": "git@github.com:dxw-wordpress-plugins/" - }, - "plugins": [ - {"name": "akismet"}, - {"name": "advanced-custom-fields-pro"} - ] - }'; - allow('file_get_contents')->toBeCalled()->andReturn($whippetContents); - allow('sha1')->toBeCalled()->andReturn('a_matching_sha'); - expect('sha1')->toBeCalled()->once()->with($whippetContents); - allow($this->whippetLock)->toReceive('getHash')->andReturn('a_matching_sha'); - allow($this->whippetJson)->toReceive('getDependencies')->andReturn([], [ - [ - 'name' => 'akismet' - ], - [ - 'name' => 'advanced-custom-fields-pro' - ] - ]); - allow($this->whippetLock)->toReceive('getDependencies')->andReturn([], [ - [ - 'name' => 'akismet' - ] - ]); - $result = $this->validator->validate(); - expect($result)->toBeAnInstanceOf(\Result\Result::class); - expect($result->getErr())->toEqual('Mismatched dependencies count for type plugins'); - }); - }); - context('but entries in .json and .lock do not match', function () { - it('returns an error', function () { - $whippetContents = '{ - "src": { - "plugins": "git@github.com:dxw-wordpress-plugins/" - }, - "plugins": [ - {"name": "akismet"}, - {"name": "advanced-custom-fields-pro"} - ] - }'; - allow('file_get_contents')->toBeCalled()->andReturn($whippetContents); - allow('sha1')->toBeCalled()->andReturn('a_matching_sha'); - expect('sha1')->toBeCalled()->once()->with($whippetContents); - allow($this->whippetLock)->toReceive('getHash')->andReturn('a_matching_sha'); - allow($this->whippetJson)->toReceive('getDependencies')->andReturn([], [ - [ - 'name' => 'akismet' - ], - [ - 'name' => 'advanced-custom-fields-pro' - ] - ]); - allow($this->whippetLock)->toReceive('getDependencies')->andReturn([], [ - [ - 'name' => 'akismet' - ], - [ - 'name' => 'some-other-plugin' - ] - ]); - $result = $this->validator->validate(); - expect($result)->toBeAnInstanceOf(\Result\Result::class); - expect($result->getErr())->toEqual('No entry found in whippet.lock for plugins: advanced-custom-fields-pro'); - }); - }); - context('but an entry in .lock is malformed', function () { - it('returns an error', function () { - $whippetContents = '{ - "src": { - "plugins": "git@github.com:dxw-wordpress-plugins/" - }, - "plugins": [ - {"name": "akismet"}, - {"name": "advanced-custom-fields-pro"} - ] - }'; - allow('file_get_contents')->toBeCalled()->andReturn($whippetContents); - allow('sha1')->toBeCalled()->andReturn('a_matching_sha'); - expect('sha1')->toBeCalled()->once()->with($whippetContents); - allow($this->whippetLock)->toReceive('getHash')->andReturn('a_matching_sha'); - allow($this->whippetJson)->toReceive('getDependencies')->andReturn([], [ - [ - 'name' => 'akismet' - ], - [ - 'name' => 'advanced-custom-fields-pro' - ] - ]); - allow($this->whippetLock)->toReceive('getDependencies')->andReturn([], [ - [ - 'name' => 'akismet', - 'src' => 'a_src_1', - 'revision' => 'a_revision_1' - ], - [ - 'name' => 'advanced-custom-fields-pro', - 'src' => 'a_src_2', - ] - ]); - $result = $this->validator->validate(); - expect($result)->toBeAnInstanceOf(\Result\Result::class); - expect($result->getErr())->toEqual('Missing revision property in whippet.lock for plugins: advanced-custom-fields-pro'); - }); - }); - context('but an entry in .json is missing a ref when --enforce-refs is set', function () { - it('returns an error', function () { - $whippetContents = '{ - "src": { - "plugins": "git@github.com:dxw-wordpress-plugins/" - }, - "plugins": [ - {"name": "akismet", "ref": "v1"}, - {"name": "advanced-custom-fields-pro"} - ] - }'; - allow('file_get_contents')->toBeCalled()->andReturn($whippetContents); - allow('sha1')->toBeCalled()->andReturn('a_matching_sha'); - expect('sha1')->toBeCalled()->once()->with($whippetContents); - allow($this->whippetLock)->toReceive('getHash')->andReturn('a_matching_sha'); - allow($this->whippetJson)->toReceive('getDependencies')->andReturn([], [ - [ - 'name' => 'akismet', - 'ref' => 'v1' - ], - [ - 'name' => 'advanced-custom-fields-pro' - ] - ]); - allow($this->whippetLock)->toReceive('getDependencies')->andReturn([], [ - [ - 'name' => 'akismet', - 'src' => 'a_src_1', - 'revision' => 'a_revision_1' - ], - [ - 'name' => 'advanced-custom-fields-pro', - 'src' => 'a_src_2', - 'revision' => 'a_revision_2' - ] - ]); - ob_start(); - $result = $this->validator->validate(true); - $output = ob_get_clean(); - expect($result->getErr())->toEqual("Missing reference in whippet.json for plugins: advanced-custom-fields-pro"); - expect($result)->toBeAnInstanceOf(\Result\Result::class); - expect($result->isErr())->toEqual(true); - }); - }); - context('but an entry in whippet.json is missing a ref when --enforce-refs is not set', function () { - it('returns an ok result', function () { - $whippetContents = '{ - "src": { - "plugins": "git@github.com:dxw-wordpress-plugins/" - }, - "plugins": [ - {"name": "akismet", "ref": "v1"}, - {"name": "advanced-custom-fields-pro"} - ] - }'; - allow('file_get_contents')->toBeCalled()->andReturn($whippetContents); - allow('sha1')->toBeCalled()->andReturn('a_matching_sha'); - expect('sha1')->toBeCalled()->once()->with($whippetContents); - allow($this->whippetLock)->toReceive('getHash')->andReturn('a_matching_sha'); - allow($this->whippetJson)->toReceive('getDependencies')->andReturn([], [ - [ - 'name' => 'akismet', - 'ref' => 'v1' - ], - [ - 'name' => 'advanced-custom-fields-pro' - ] - ]); - allow($this->whippetLock)->toReceive('getDependencies')->andReturn([], [ - [ - 'name' => 'akismet', - 'src' => 'a_src_1', - 'revision' => 'a_revision_1' - ], - [ - 'name' => 'advanced-custom-fields-pro', - 'src' => 'a_src_2', - 'revision' => 'a_revision_2' - ] - ]); - ob_start(); - $result = $this->validator->validate(); - $output = ob_get_clean(); - expect($output)->toEqual("Valid whippet.json and whippet.lock \n"); - expect($result)->toBeAnInstanceOf(\Result\Result::class); - expect($result->isErr())->toEqual(false); - }); - }); - context('and everything is good', function () { - it('returns an ok result', function () { - $whippetContents = '{ - "src": { - "plugins": "git@github.com:dxw-wordpress-plugins/" - }, - "plugins": [ - {"name": "akismet"}, - {"name": "advanced-custom-fields-pro"} - ] - }'; - allow('file_get_contents')->toBeCalled()->andReturn($whippetContents); - allow('sha1')->toBeCalled()->andReturn('a_matching_sha'); - expect('sha1')->toBeCalled()->once()->with($whippetContents); - allow($this->whippetLock)->toReceive('getHash')->andReturn('a_matching_sha'); - allow($this->whippetJson)->toReceive('getDependencies')->andReturn([], [ - [ - 'name' => 'akismet' - ], - [ - 'name' => 'advanced-custom-fields-pro' - ] - ]); - allow($this->whippetLock)->toReceive('getDependencies')->andReturn([], [ - [ - 'name' => 'akismet', - 'src' => 'a_src_1', - 'revision' => 'a_revision_1' - ], - [ - 'name' => 'advanced-custom-fields-pro', - 'src' => 'a_src_2', - 'revision' => 'a_revision_2' - ] - ]); - ob_start(); - $result = $this->validator->validate(); - $output = ob_get_clean(); - expect($output)->toEqual("Valid whippet.json and whippet.lock \n"); - expect($result)->toBeAnInstanceOf(\Result\Result::class); - expect($result->isErr())->toEqual(false); - }); - }); - }); - }); -}); diff --git a/src/Dependencies/DependencyTypes.php b/src/Dependencies/DependencyTypes.php deleted file mode 100644 index e3de5afd..00000000 --- a/src/Dependencies/DependencyTypes.php +++ /dev/null @@ -1,16 +0,0 @@ -factory = $factory; - $this->dir = $dir; - } - - public function describe() - { - $resultLoad = $this->loadWhippetLock(); - if ($resultLoad->isErr()) { - return $resultLoad; - } - $git = new \Dxw\Whippet\Git\Git($this->dir); - $results = []; - foreach (DependencyTypes::getDependencyTypes() as $type) { - foreach ($this->lockFile->getDependencies($type) as $dep) { - $result = $git::tag_for_commit($dep['src'], $dep['revision']); - if ($result->isErr()) { - return $result; - } - $results[$type][$dep["name"]] = $result->unwrap(); - } - } - $pretty_results = json_encode($results, JSON_PRETTY_PRINT); - printf($pretty_results); - - return \Result\Result::ok(); - } - - private function loadWhippetLock() - { - $result = $this->factory->callStatic('\\Dxw\\Whippet\\Files\\WhippetLock', 'fromFile', $this->dir.'/whippet.lock'); - if ($result->isErr()) { - return $result; - } else { - $this->lockFile = $result->unwrap(); - } - - return \Result\Result::ok(); - } -} diff --git a/src/Dependencies/Installer.php b/src/Dependencies/Installer.php deleted file mode 100644 index e76475c0..00000000 --- a/src/Dependencies/Installer.php +++ /dev/null @@ -1,149 +0,0 @@ -factory = $factory; - $this->dir = $dir; - $this->inspectionChecker = $inspection_checker; - } - - public function installAll() - { - $result = $this->loadWhippetFiles(); - if ($result->isErr()) { - return $result; - } - - $dependencies = []; - - foreach (DependencyTypes::getDependencyTypes() as $type) { - $dependencies[$type] = $this->lockFile->getDependencies($type); - } - - return $this->install($dependencies); - } - - public function installSingle($dep) - { - //Will only get here if $dep is valid format and matches an entry in whippet.json - - $result = $this->loadWhippetFiles(); - if ($result->isErr()) { - return $result; - } - - $type = explode('/', $dep)[0]; - $name = explode('/', $dep)[1]; - - foreach ($this->lockFile->getDependencies($type) as $dep) { - if ($dep['name'] === $name) { - return $this->install([$type => [$dep]]); - } - } - } - - private function install(array $dependencies) - { - $count = 0; - - foreach ($dependencies as $type => $typeDependencies) { - foreach ($typeDependencies as $dependency) { - $result = $this->installDependency($type, $dependency); - if ($result->isErr()) { - return $result; - } - - echo $this->inspectionDetailsMessage($type, $dependency); - echo "\n"; - - ++$count; - } - } - - if ($count === 0) { - echo "whippet.lock contains nothing to install\n"; - } - - return \Result\Result::ok(); - } - - private function loadWhippetFiles() - { - if (!is_file($this->dir.'/whippet.json')) { - return \Result\Result::err('whippet.json not found'); - } - - $result = $this->factory->callStatic('\\Dxw\\Whippet\\Files\\WhippetLock', 'fromFile', $this->dir.'/whippet.lock'); - if ($result->isErr()) { - return \Result\Result::err(sprintf('whippet.lock: %s', $result->getErr())); - } - $this->lockFile = $result->unwrap(); - - $contents = file_get_contents($this->dir.'/whippet.json'); - - // Strip CR for git/Windows compatibility - $contents = strtr($contents, ["\r" => '']); - - $hash = sha1($contents); - if ($this->lockFile->getHash() !== $hash) { - return \Result\Result::err('mismatched hash - run `whippet dependencies update` first'); - } - - return \Result\Result::ok(); - } - - private function installDependency($type, $dep) - { - $path = $this->dir.'/wp-content/'.$type.'/'.$dep['name']; - - $git = $this->factory->newInstance('\\Dxw\\Whippet\\Git\\Git', $path); - - if (!$git->is_repo()) { - echo sprintf("[Adding %s/%s]\n", $type, $dep['name']); - $result = $git->clone_repo($dep['src']); - - if ($result === false) { - return \Result\Result::err('could not clone repository'); - } - } else { - echo sprintf("[Checking %s/%s]\n", $type, $dep['name']); - } - - $result = $git->checkout($dep['revision']); - if ($result === false) { - return \Result\Result::err('could not checkout revision'); - } - - return \Result\Result::ok(); - } - - private function inspectionDetailsMessage($type, $dep) - { - $result = $this->inspectionChecker->check($type, $dep); - - if (!$result->isErr()) { - $inspectionDetails = $result->unwrap(); - if (!empty($inspectionDetails)) { - $message = sprintf("%s\n", $inspectionDetails); - } else { - $message = null; - } - } else { - $error = $result->getErr(); - $message = sprintf("[ERROR] %s\n", $error); - } - return $message; - } -} diff --git a/src/Dependencies/Updater.php b/src/Dependencies/Updater.php deleted file mode 100644 index d7977dc1..00000000 --- a/src/Dependencies/Updater.php +++ /dev/null @@ -1,220 +0,0 @@ -factory = $factory; - $this->dir = $dir; - } - - public function updateSingle($dep) - { - $result = $this->factory->callStatic('\\Dxw\\Whippet\\Files\\WhippetLock', 'fromFile', $this->dir.'/whippet.lock'); - if ($result->isErr()) { - echo "No whippet.lock file exists, you need to run `whippet deps update` to generate one before you can update a specific dependency. \n"; - return \Result\Result::err(sprintf('whippet.lock: %s', $result->getErr())); - } - - if (strpos($dep, '/') === false) { - echo "Dependency should be in format [type]/[name]. \n"; - return \Result\Result::err('Incorrect dependency format'); - } - - $type = explode('/', $dep)[0]; - $name = explode('/', $dep)[1]; - - $result = $this->prepareForUpdate(); - if ($result->isErr()) { - return $result; - } - - $dep = $this->jsonFile->getDependency($type, $name); - if ($dep === []) { - return \Result\Result::err('No matching dependency in whippet.json'); - } - - return $this->update([$type => [$dep]]); - } - - public function updateAll() - { - $result = $this->prepareForUpdate(); - if ($result->isErr()) { - return $result; - } - - $allDependencies = []; - - foreach (DependencyTypes::getDependencyTypes() as $type) { - $allDependencies[$type] = $this->jsonFile->getDependencies($type); - } - - return $this->update($allDependencies); - } - - private function update(array $dependencies) - { - $this->updateHash(); - $this->loadGitignore(); - $count = 0; - foreach ($dependencies as $type => $typeDependencies) { - foreach ($typeDependencies as $dep) { - echo sprintf("[Updating %s/%s]\n", $type, $dep['name']); - $result = $this->addDependencyToLockfile($type, $dep); - if ($result->isErr()) { - return $result; - } - ++$count; - } - } - $this->saveChanges(); - - if ($count === 0) { - echo "whippet.json contains no dependencies\n"; - } - return \Result\Result::ok(); - } - - private function prepareForUpdate() - { - $result = $this->loadWhippetFiles(); - if ($result->isErr()) { - return $result; - } - return \Result\Result::ok(); - } - - private function saveChanges() - { - $this->lockFile->saveToPath($this->dir.'/whippet.lock'); - $this->createGitIgnore(); - } - - private function loadWhippetFiles() - { - $result = $this->factory->callStatic('\\Dxw\\Whippet\\Files\\WhippetJson', 'fromFile', $this->dir.'/whippet.json'); - if ($result->isErr()) { - return \Result\Result::err(sprintf('whippet.json: %s', $result->getErr())); - } - $this->jsonFile = $result->unwrap(); - - $result = $this->factory->callStatic('\\Dxw\\Whippet\\Files\\WhippetLock', 'fromFile', $this->dir.'/whippet.lock'); - if ($result->isErr()) { - $this->lockFile = $this->factory->newInstance('\\Dxw\\Whippet\\Files\\WhippetLock', []); - } else { - $this->lockFile = $result->unwrap(); - } - - return \Result\Result::ok(); - } - - private function updateHash() - { - $contents = file_get_contents($this->dir.'/whippet.json'); - - // Strip CR for git/Windows compatibility - $contents = strtr($contents, ["\r" => '']); - - $jsonHash = sha1($contents); - $this->lockFile->setHash($jsonHash); - } - - private function createGitIgnore() - { - foreach (DependencyTypes::getDependencyTypes() as $type) { - foreach ($this->jsonFile->getDependencies($type) as $dep) { - $this->addDependencyToIgnoresArray($type, $dep['name']); - } - } - $this->gitignore->save_ignores(array_unique($this->ignores)); - } - - private function loadGitignore() - { - $this->gitignore = $this->factory->newInstance('\\Dxw\\Whippet\\Git\\Gitignore', (string) $this->dir); - - $this->ignores = []; - if (is_file($this->dir.'/.gitignore')) { - $this->ignores = $this->gitignore->get_ignores(); - } - - // Iterate through locked dependencies and remove from gitignore - foreach (DependencyTypes::getDependencyTypes() as $type) { - foreach ($this->lockFile->getDependencies($type) as $dep) { - $line = $this->getGitignoreDependencyLine($type, $dep['name']); - $index = array_search($line, $this->ignores); - if ($index !== false) { - unset($this->ignores[$index]); - } - } - } - } - - private function addDependencyToIgnoresArray($type, $name) - { - $this->ignores[] = $this->getGitignoreDependencyLine($type, $name); - } - - private function getGitignoreDependencyLine($type, $name) - { - return '/wp-content/'.$type.'/'.$name."\n"; - } - - private function addDependencyToLockfile($type, array $dep) - { - if (isset($dep['src'])) { - $src = $dep['src']; - } else { - $sources = $this->jsonFile->getSources(); - if (!isset($sources[$type])) { - return \Result\Result::err('missing sources'); - } - $src = $sources[$type].$dep['name']; - } - - if (isset($dep['ref'])) { - $ref = $dep['ref']; - $commitResult = $this->fetchRef($src, $ref); - } else { - $commitResult = $this->fetchDefault($src); - } - - if ($commitResult->isErr()) { - return \Result\Result::err(sprintf('git command failed: %s', $commitResult->getErr())); - } - - $this->lockFile->addDependency($type, $dep['name'], $src, $commitResult->unwrap()); - - return \Result\Result::ok(); - } - - private function fetchRef(string $src, string $ref): \Result\Result - { - return $this->factory->callStatic('\\Dxw\\Whippet\\Git\\Git', 'ls_remote', $src, $ref); - } - - // Fetch the default branch - // That may be `main` or `master` - private function fetchDefault(string $src): \Result\Result - { - $main = $this->fetchRef($src, 'main'); - - if (!$main->isErr()) { - return $main; - } - - return $this->fetchRef($src, 'master'); - } -} diff --git a/src/Dependencies/Validator.php b/src/Dependencies/Validator.php deleted file mode 100644 index 209638ec..00000000 --- a/src/Dependencies/Validator.php +++ /dev/null @@ -1,111 +0,0 @@ -factory = $factory; - $this->dir = $dir; - } - - public function validate(bool $enforceRefs = false) - { - $whippetLock = $this->loadWhippetLock(); - if ($whippetLock->isErr()) { - return \Result\Result::err(sprintf( - 'whippet.lock error: %s', - $whippetLock->getErr() - )); - } else { - $whippetLock = $whippetLock->unwrap(); - } - - $whippetJson = $this->loadWhippetJson(); - if ($whippetJson->isErr()) { - return \Result\Result::err(sprintf( - 'whippet.json error: %s', - $whippetJson->getErr() - )); - } else { - $whippetJson = $whippetJson->unwrap(); - } - - // Check hashes - if ($this->whippetJsonHash() !== $whippetLock->getHash()) { - return \Result\Result::err( - 'hash mismatch between whippet.json and whippet.lock' - ); - }; - - // Check that entries in whippet.json - // match entries in whippet.lock - foreach (DependencyTypes::getDependencyTypes() as $type) { - $whippetJsonDependencies = $whippetJson->getDependencies($type); - $whippetLockDependencies = $whippetLock->getDependencies($type); - if (count($whippetJsonDependencies) !== count($whippetLockDependencies)) { - return \Result\Result::err(sprintf('Mismatched dependencies count for type %s', $type)); - } - - foreach ($whippetJsonDependencies as $whippetJsonDependency) { - if (!$this->lockMatchFoundForDependency($whippetJsonDependency, $whippetLockDependencies)) { - return \Result\Result::err(sprintf('No entry found in whippet.lock for %s: %s', $type, $whippetJsonDependency["name"])); - } - if ($enforceRefs) { - if (!array_key_exists('ref', $whippetJsonDependency)) { - return \Result\Result::err(sprintf("Missing reference in whippet.json for %s: %s", $type, $whippetJsonDependency["name"])); - } - } - } - - foreach ($whippetLockDependencies as $whippetLockDependency) { - foreach (['revision', 'src'] as $property) { - if (!array_key_exists($property, $whippetLockDependency)) { - return \Result\Result::err(sprintf("Missing %s property in whippet.lock for %s: %s", $property, $type, $whippetLockDependency["name"])); - } - } - } - } - - echo "Valid whippet.json and whippet.lock \n"; - - return \Result\Result::ok(); - } - - private function loadWhippetLock() - { - return $this->factory->callStatic('\\Dxw\\Whippet\\Files\\WhippetLock', 'fromFile', $this->dir.'/whippet.lock'); - } - - private function loadWhippetJson() - { - return $this->factory->callStatic('\\Dxw\\Whippet\\Files\\WhippetJson', 'fromFile', $this->dir.'/whippet.json'); - } - - private function whippetJsonHash() - { - $contents = file_get_contents($this->dir.'/whippet.json'); - - // Strip CR for git/Windows compatibility - $contents = strtr($contents, ["\r" => '']); - - return sha1($contents); - } - - private function lockMatchFoundForDependency($whippetJsonDependency, $whippetLockDependencies) - { - $matchFound = false; - foreach ($whippetLockDependencies as $whippetLockDependency) { - if ($whippetJsonDependency["name"] == $whippetLockDependency["name"]) { - $matchFound = true; - } - } - return $matchFound; - } -} diff --git a/src/Factory.php b/src/Factory.php deleted file mode 100644 index 5c0ccc8b..00000000 --- a/src/Factory.php +++ /dev/null @@ -1,25 +0,0 @@ -newInstanceArgs($args); - } - - public function callStatic() - { - $args = func_get_args(); - $className = array_shift($args); - $methodName = array_shift($args); - - return call_user_func_array([$className, $methodName], $args); - } -} diff --git a/src/Files/Base.php b/src/Files/Base.php deleted file mode 100644 index 53492f0a..00000000 --- a/src/Files/Base.php +++ /dev/null @@ -1,37 +0,0 @@ -data = $data; - } - - public function saveToPath(/* string */ $path) - { - file_put_contents($path, json_encode($this->data, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES)."\n"); - } -} diff --git a/src/Files/WhippetJson.php b/src/Files/WhippetJson.php deleted file mode 100644 index 396ff435..00000000 --- a/src/Files/WhippetJson.php +++ /dev/null @@ -1,35 +0,0 @@ -data[$type])) { - return $this->data[$type]; - } else { - return []; - } - } - - public function getDependency(/* string */ $type, /* string */ $name) - { - if (isset($this->data[$type])) { - foreach ($this->getDependencies($type) as $dep) { - if ($dep['name'] === $name) { - return $dep; - } - } - } - return []; - } - - public function getSources() - { - return $this->data['src']; - } -} diff --git a/src/Files/WhippetLock.php b/src/Files/WhippetLock.php deleted file mode 100644 index bbcae3af..00000000 --- a/src/Files/WhippetLock.php +++ /dev/null @@ -1,45 +0,0 @@ -data[$type])) { - return []; - } - - return $this->data[$type]; - } - - public function getHash() - { - return $this->data['hash']; - } - - public function setHash(/* string */ $hash) - { - $this->data['hash'] = $hash; - } - - public function addDependency(/* string */ $type, /* string */ $name, /* string */ $src, /* string */ $revision) - { - if (isset($this->data[$type])) { - foreach ($this->data[$type] as $key => $dependency) { - if ($name === $dependency['name']) { - array_splice($this->data[$type], $key, 1); - } - } - } - - $this->data[$type][] = [ - 'name' => $name, - 'src' => $src, - 'revision' => $revision, - ]; - } -} diff --git a/src/Git/Git.php b/src/Git/Git.php deleted file mode 100644 index c7482487..00000000 --- a/src/Git/Git.php +++ /dev/null @@ -1,451 +0,0 @@ -repo_path = $repo_path; - } - - public static function init($dir) - { - $output = []; - $return = ''; - - exec(sprintf('git init %s', escapeshellarg($dir)), $output, $return); - - return [$output, $return]; - } - - public function is_repo() - { - return file_exists("{$this->repo_path}/.git"); - } - - private function is_github_repository($repository) - { - $pos = strpos($repository, 'github.com'); - return $pos !== false; - } - - /** Issue a warning to the user if a GitHub repository is archived. - * - * Note that we specifically ignore any non-GitHub repository for now, - * which is why we have not factored this code into its own class structure. - * - * See: https://docs.github.com/en/rest/repos/repos?get-a-repository - */ - public function check_is_archived_github_repository($repository) - { - if (!$this->is_github_repository($repository)) { - return; - } - $baseurl = 'https://api.github.com/repos'; # Must not have a trailing slash. - $substrings = explode('/', $repository); - $num_substrings = count($substrings); - # If the URL is http formatted: ['https', 'github.com', 'org', 'repo'] - # If the URL is ssh formatted: ['git@git.github.com:org', 'repo'] - if ($num_substrings < 2) { - return false; - } - $repo = $substrings[$num_substrings - 1]; - if (false !== strpos($repo, '.git')) { # repo.git - $repo = str_replace('.git', '', $repo); - } - - if (false !== strpos($repository, '@')) { - # ssh formatted... - $org = explode(':', $substrings[$num_substrings - 2])[1]; - } else { - # http formatted... - $org = $substrings[$num_substrings - 2]; - } - $api_url = join('/', [$baseurl, $org, $repo]); - - $curl = curl_init(); - curl_setopt($curl, CURLOPT_URL, $api_url); - curl_setopt($curl, CURLOPT_USERAGENT, 'Whippet'); - curl_setopt($curl, CURLOPT_FOLLOWLOCATION, true); - curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1); - $raw_json = curl_exec($curl); - $json = json_decode($raw_json); - curl_close($curl); - if (!is_null($json) && property_exists($json, 'archived') && $json->archived) { - echo "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n"; - echo "!! WARNING: GitHub repo is archived. This dependency !!\n"; - echo "!! should be replaced before the repo is removed. !!\n"; - echo "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n"; - } - } - - public function checkout($revision) - { - list($output, $return) = $this->run_command(['git', 'remote', 'get-url', 'origin']); - if ($return === 0) { - $this->check_is_archived_github_repository($output[0]); - } - - list($output, $return) = $this->run_command(['git', 'fetch', '-a', '--force', '&&', 'git', 'checkout', $revision]); - - return $this->check_git_return('Checkout failed', $return, $output); - } - - public function hard_reset($revision = 'HEAD') - { - list($output, $return) = $this->run_command(['git', 'reset', '--hard', $revision]); - - return $this->check_git_return('Reset --hard failed', $return, $output); - } - - public function mixed_reset($revision = 'HEAD') - { - list($output, $return) = $this->run_command(['git', 'reset', '--mixed', $revision]); - - return $this->check_git_return('Reset --mixed failed', $return, $output); - } - - public function clone_repo($repository) - { - $this->check_is_archived_github_repository($repository); - - list($output, $return) = $this->run_command(['git', 'clone', $repository, $this->repo_path], false); - - if (!$this->check_git_return('Clone failed', $return, $output)) { - return false; - } - - return true; - } - - public function clone_no_checkout($repository) - { - $this->check_is_archived_github_repository($repository); - - $tmpdir = $this->get_tmpdir(); - - list($output, $return) = $this->run_command(['git', 'clone', '--no-checkout', $repository, $tmpdir], false); - - if (!$this->check_git_return('No-checkout clone failed', $return, $output)) { - return false; - } - - $this->run_command(['mv', $tmpdir . '/.git', $this->repo_path]); - - return true; - } - - public function submodule_update() - { - list($output, $return) = $this->run_command(['git', 'submodule', 'update', '--init', '--recursive']); - - if (!$this->check_git_return('submodule update failed', $return, $output)) { - return false; - } - - return true; - } - - public function submodule_status() - { - list($output, $return) = $this->run_command(['git', 'submodule', 'status']); - - if (!$this->check_git_return('submodule status failed', $return, $output)) { - return false; - } - - $submodules = []; - - foreach ($output as $line) { - if (preg_match('/(\+?U?-?)([a-z0-9]{40}) ([^\(]+)([^\)]*)/', trim($line), $matches)) { - $submodule = new \stdClass(); - $submodule->status = trim($matches[1]); - $submodule->commit = trim($matches[2]); - $submodule->dir = trim($matches[3]); - $submodule->description = preg_replace('/^[\s\(]*/', '', $matches[4]); - $submodule->remotes = (new self("{$this->repo_path}/{$submodule->dir}"))->get_remotes(); - - $submodules[$submodule->dir] = $submodule; - } else { - echo "Failed to parse: {$line}\n"; - - return false; - } - } - - return $submodules; - } - - public function submodule_add($repo, $path) - { - list($output, $return) = $this->run_command(['git', 'submodule', 'add', $repo, $path]); - - if (!$this->check_git_return('submodule status failed', $return, $output)) { - return false; - } - - return true; - } - - public function delete_repo() - { - $this->run_command(['rm', '-rf', $this->repo_path], false); - } - - public function current_commit() - { - list($output, $return) = $this->run_command(['git', 'rev-parse', 'HEAD']); - - if (!$this->check_git_return('Checkout failed', $return, $output)) { - return false; - } - - return $output[0]; - } - - public function local_revision_commit($revision) - { - list($output, $return) = $this->run_command(['git', 'show-ref']); - - if (!$this->check_git_return('show-ref failed', $return, $output)) { - return false; - } - - foreach ($this->parse_ref_list($output) as $ref) { - if ($ref->name == $revision) { - return $ref->commit; - } - } - - return false; - } - - public function get_remotes() - { - list($output, $return) = $this->run_command(['git', 'remote', '-v']); - - if (!$this->check_git_return('git remote failed', $return, $output)) { - return false; - } - - $remotes = []; - - foreach ($output as $line) { - if (preg_match('/^([^\s]+)\s+([^\s]+)/', trim($line), $matches)) { - $remotes[$matches[1]] = $matches[2]; - } else { - echo "Failed to parse: {$line}\n"; - - return false; - } - } - - return $remotes; - } - - public function remote_revision_commit($revision) - { - list($output, $return) = $this->run_command(['git', 'ls-remote']); - - if (!$this->check_git_return('ls-remote failed', $return, $output)) { - return false; - } - - foreach ($this->parse_ref_list($output) as $ref) { - if ($ref->name == $revision) { - return $ref->commit; - } - } - - return $this->parse_ref_list($output); - } - - public function fetch() - { - list($output, $return) = $this->run_command(['git', 'fetch', '-a', '--force']); - - return $this->check_git_return('Checkout failed', $return, $output); - } - - public function rm($path, $rf = false) - { - list($output, $return) = $this->run_command(['git', 'rm', $rf ? '-rf' : '', $path]); - - return $this->check_git_return('rm failed', $return, $output); - } - - public function add($path) - { - list($output, $return) = $this->run_command(['git', 'add', $path]); - - return $this->check_git_return('Add failed', $return, $output); - } - - public function commit($message) - { - list($output, $return) = $this->run_command(['git', 'commit', '-m', $message]); - - return $this->check_git_return('Checkout failed', $return, $output); - } - - protected function parse_ref_list($reflist) - { - $refs = []; - foreach ($reflist as $line) { - if (preg_match("/^([a-z0-9]{40})\s+(.+)$/", $line, $matches)) { - $ref = new \stdClass(); - - $ref->commit = $matches[1]; - - if (preg_match('#^refs/(tags|heads)/(.+)$#', $matches[2], $matches)) { - $ref->tag = $matches[1] == 'tags'; - $ref->branch = $matches[1] == 'branch'; - $ref->name = $matches[2]; - - $refs[] = $ref; - } - } - } - - return $refs; - } - - /** - * This function checks to see whether git successfully ran. If so, - * it returns true. If not, it prints the supplied message along with - * git's output and returns false. - * - * $message An error message to display on failure - * $return Git's return code, as set by exec() - * $output Git's output code, as set by exec() - */ - protected function check_git_return($message, $return, $output) - { - if ($return !== 0) { - echo "{$message}:\n\n".implode("\n", $output); - - return false; - } - - return true; - } - - /** - * Runs the specified git command, with some basic sanity checking to - * ensure that required repos and directories exist. - * - * $command The command to be run - * $cd If true, Whippet will change its working directory to repo_path before executing $command - * - * See also: this::__construct. - * @param array $cmd - * @param bool $cd - * @return array - */ - protected function run_command(array $cmd, $cd = true) - { - $output = []; - $return = 0; - $command = ''; - - foreach ($cmd as $value) { - $command .= !in_array($value, $this->command_separators, true) ? escapeshellarg($value) : $value; - $command .= ' '; - } - - if ($cd && !file_exists($this->repo_path)) { - echo "Error: directory does not exist ({$this->repo_path})\n"; - exit(1); - } - - if ($cd) { - $cd = sprintf("cd %s && ", escapeshellarg($this->repo_path)); - } else { - $cd = ''; - } - - exec("{$cd}{$command}", $output, $return); - //echo ("{$cd}{$command}\n"); - - return [$output, $return]; - } - - /** - * Obtains a valid directory for temporary files on the current system, or in a specified location. - * - * $in_dir If supplied, the temporary directory will be created as a subdirectory of this path. If false or missing, the system's default temporary file location will be used. - */ - public function get_tmpdir($in_dir = false) - { - if (!$in_dir) { - $in_dir = sys_get_temp_dir(); - } - - do { - $tmp_dir = $in_dir.'/'.md5(microtime()); - } while (file_exists($tmp_dir)); - - return $tmp_dir; - } - - public static function ls_remote($repo, $ref) - { - exec(sprintf('git ls-remote %s %s', escapeshellarg($repo), escapeshellarg($ref)), $output, $return); - - if ($return !== 0) { - return \Result\Result::err('git error'); - } - - if (count($output) === 0) { - return \Result\Result::err('ref not found'); - } - - return \Result\Result::ok(explode("\t", $output[0])[0]); - } - - public static function tag_for_commit($repo, $commit_hash) - { - exec(sprintf('git ls-remote %s', escapeshellarg($repo)), $output, $return); - - if ($return !== 0) { - return \Result\Result::err('git error when attempting to access ' . $repo); - } - - if (count($output) === 0) { - return \Result\Result::err('no references found for repo ' . $repo); - } - - $tags_array = array_values(array_filter($output, function ($ref) use ($commit_hash) { - return strpos($ref, $commit_hash) === 0 && strpos($ref, 'refs/tags') !== false; - })); - - if (empty($tags_array)) { - return \Result\Result::ok('No tags for commit ' . $commit_hash); - } - - usort($tags_array, function ($a, $b) { - return strlen($b) <=> strlen($a); - }); - - $resultArray = explode('/', $tags_array[0]); - $result = str_replace("^{}", "", end($resultArray)); - - return \Result\Result::ok($result); - } -}; diff --git a/src/Git/Gitignore.php b/src/Git/Gitignore.php deleted file mode 100644 index b37fffb9..00000000 --- a/src/Git/Gitignore.php +++ /dev/null @@ -1,57 +0,0 @@ -ignore_file = "{$repo_path}/.gitignore"; - } - - /** - * Loads a .gitignore file into an array, with consistent line endings. - */ - public function get_ignores() - { - return $this->ensure_closing_newline(file($this->ignore_file)); - } - - /** - * Saves the supplied .gitignore lines back to the file. - */ - public function save_ignores($ignores) - { - return file_put_contents($this->ignore_file, $ignores); - } - - /** - * Ensures that the last line in the ignores has a line return. - * - * TODO: This class, and its callers, should be refactored to remove the line - * ending on each element in this array - */ - private function ensure_closing_newline($ignores) - { - $index_of_last_line = count($ignores) - 1; - $last_line = $index_of_last_line >= 0 ? $ignores[$index_of_last_line] : 0; - $last_character = substr($last_line, -1); - - if ($last_character != "\n") { - $ignores[$index_of_last_line] = $last_line."\n"; - } - - return $ignores; - } -} diff --git a/src/Models/Inspection.php b/src/Models/Inspection.php deleted file mode 100644 index 87078c53..00000000 --- a/src/Models/Inspection.php +++ /dev/null @@ -1,32 +0,0 @@ -date = date_create($date_string); - $this->versions = $versions; - $this->result = $result; - $this->url = $url; - } -} diff --git a/src/Modules/Dependencies.php b/src/Modules/Dependencies.php deleted file mode 100644 index 7a0f5d5f..00000000 --- a/src/Modules/Dependencies.php +++ /dev/null @@ -1,102 +0,0 @@ -factory = new \Dxw\Whippet\Factory(); - $this->projectDirectory = \Dxw\Whippet\ProjectDirectory::find(getcwd()); - $base_api = new \Dxw\Whippet\Services\BaseApi(); - $json_api = new \Dxw\Whippet\Services\JsonApi($base_api); - if (isset($_SERVER['INSPECTIONS_API_HOST'])) { - $inspections_api_host = $_SERVER['INSPECTIONS_API_HOST']; - } else { - $inspections_api_host = 'https://advisories.dxw.com'; - } - $inspections_api_path = '/wp-json/v1/inspections/'; - $this->inspections_api = new \Dxw\Whippet\Services\InspectionsApi($inspections_api_host, $inspections_api_path, $json_api); - } - - public function commands() - { - $inspections_host_option = function ($option_parser) { - $option_parser->addRule('c|disable-inspections-check', 'Disables the calls to the dxw Security API which check for security inspections of plugins'); - }; - $this->command('install', 'Installs dependencies', $inspections_host_option); - $this->command('update', 'Updates dependencies to their latest versions. Use deps update [type]/[name] to update a specific dependency', $inspections_host_option); - $this->command('validate', 'Validate whippet.json and whippet.lock files', function ($option_parser) { - $option_parser->addRule('r|enforce-refs', "Enforce refs for all whippet dependencies"); - }); - $this->command('describe', 'List dependencies and their versions'); - } - - private function exitIfError(\Result\Result $result) - { - if ($result->isErr()) { - echo sprintf("ERROR: %s\n", $result->getErr()); - exit(1); - } - } - - private function getDirectory() - { - $this->exitIfError($this->projectDirectory); - - return $this->projectDirectory->unwrap(); - } - - public function install() - { - $dir = $this->getDirectory(); - $installer = new \Dxw\Whippet\Dependencies\Installer($this->factory, $dir, $this->inspectionChecker()); - - $this->exitIfError($installer->installAll()); - } - - public function update($dep = null) - { - $dir = $this->getDirectory(); - $updater = new \Dxw\Whippet\Dependencies\Updater($this->factory, $dir); - $installer = new \Dxw\Whippet\Dependencies\Installer($this->factory, $dir, $this->inspectionChecker()); - - if (is_null($dep)) { - $this->exitIfError($updater->updateAll()); - $this->exitIfError($installer->installAll()); - } else { - $this->exitIfError($updater->updateSingle($dep)); - $this->exitIfError($installer->installSingle($dep)); - } - } - - public function validate() - { - $dir = $this->getDirectory(); - $validator = new \Dxw\Whippet\Dependencies\Validator($this->factory, $dir); - $enforceRefs = isset($this->options->{'enforce-refs'}) ? true : false; - $this->exitIfError(($validator->validate($enforceRefs))); - } - - public function describe() - { - $dir = $this->getDirectory(); - $describer = new \Dxw\Whippet\Dependencies\Describer($this->factory, $dir); - $this->exitIfError(($describer->describe())); - } - - private function inspectionChecker() - { - if (isset($this->options->{'disable-inspections-check'})) { - return new \Dxw\Whippet\Services\NullInspectionChecker(); - } else { - return new \Dxw\Whippet\Services\InspectionChecker($this->inspections_api); - } - } -} diff --git a/src/Modules/Deploy.php b/src/Modules/Deploy.php deleted file mode 100644 index 042384b5..00000000 --- a/src/Modules/Deploy.php +++ /dev/null @@ -1,206 +0,0 @@ -deploy_dir = $dir; - $this->releases_dir = "{$this->deploy_dir}/releases"; - $this->shared_dir = "{$this->deploy_dir}/shared"; - $this->public_dir = ""; - $this->releases_manifest = []; - } - - public function deploy($force, $keep, $public) - { - try { - // - // 1. Make sure the target directory does not exist (or exists and is empty) - // 2. Load or create the releases manifest - // 3. Deploy the app into the releases directory - // 4. Validate the deploy - // 5. Create or update the "current" symlink - // - - // - // Make sure the environment is sane - // - - // Got all the deploy directories? - - $this->check_and_create_dir($this->deploy_dir); - $this->check_and_create_dir($this->releases_dir); - $this->check_and_create_dir($this->shared_dir); - if (!empty($public)) { - $this->public_dir = $public; - $this->check_and_create_dir($this->public_dir); - } - - // - // Load up the manifest and create the new release - // - - $this->load_releases_manifest(); - - // TODO: add support for a release message - if (count($this->releases_manifest)) { - $release_number = $this->releases_manifest[count($this->releases_manifest) - 1]->number + 1; - } else { - $release_number = 0; - } - - $new_release = new Release($this->releases_dir, $release_number, $this->public_dir); - - // Make it. - $new_release->create($force, $public); - - // - // Did everything work? - // - - $checks = [ - // - // Is WP there? - // - - 'wp-login.php is missing; is WordPress properly deployed?' => !file_exists("{$new_release->release_dir}/wp-login.php"), - 'wp-includes/wp-db.php is missing; is WordPress properly deployed?' => !file_exists("{$new_release->release_dir}/wp-includes/wp-db.php"), - 'wp-admin/edit.php is missing; is WordPress properly deployed?' => !file_exists("{$new_release->release_dir}/wp-admin/edit.php"), - - // - // Is the app there? - // - - 'wp-content/themes is missing; is the app properly deployed?' => !file_exists("{$new_release->release_dir}/wp-content/themes"), - 'wp-content/plugins is missing; is the app properly deployed?' => !file_exists("{$new_release->release_dir}/wp-content/plugins"), - - // Is there stuff in shared? Does it look right? - 'wp-config.php is not in the shared directory.' => !file_exists("{$new_release->release_dir}/../../shared/wp-config.php"), - 'uploads directory is not in the shared directory.' => (!file_exists("{$new_release->release_dir}/../../shared/uploads") && !is_link("{$new_release->release_dir}/../../shared/uploads")), - "wp-config.php doesn't contain DB_NAME; is it valid?" => !strpos(file_get_contents("{$new_release->release_dir}/../../shared/wp-config.php"), 'DB_NAME'), - - // - // Did the symlinking work? - // - - 'wp-config.php is missing; did the symlinking fail?' => !file_exists("{$new_release->release_dir}/wp-config.php"), - 'wp-content/uploads is missing; did the symlinking fail?' => (!file_exists("{$new_release->release_dir}/wp-content/uploads") && !is_link("{$new_release->release_dir}/../../shared/uploads")), - ]; - - $release_ok = true; - $messages = []; - - foreach ($checks as $message => $failed) { - if ($failed) { - $release_ok = false; - $messages[] = "\t{$message}"; - } - } - - // - // If it was all ok: - // - - if (!$release_ok) { - $broken_release = $broken_release_prefix = "{$new_release->release_dir}.broken"; - $count = 1; - - while (file_exists($broken_release)) { - $broken_release = $broken_release_prefix."_{$count}"; - ++$count; - } - - rename("{$new_release->release_dir}", "{$broken_release}"); - - echo "Problems:\n"; - echo implode("\n", $messages); - echo "\n\nRelease did not validate; it has been moved to: $broken_release"; - - exit(1); - } else { - // If we are forcing, rejig some directories - if ($force) { - rename("{$this->releases_dir}/{$new_release->deployed_commit}", "{$this->releases_dir}/{$new_release->deployed_commit}_".($new_release->number - 1)); - rename("{$new_release->release_dir}", "{$this->releases_dir}/{$new_release->deployed_commit}"); - - $new_release->release_dir = "{$this->releases_dir}/{$new_release->deployed_commit}"; - } - - $current = "{$new_release->release_dir}/../../current"; - - // If we are not forcing, check to see if the release being deployed is the currently deployed release - if so, do nothing - if (!$force && file_exists($current) && readlink($current) == realpath($new_release->release_dir)) { - return; - } - - if (file_exists($current)) { - unlink("{$current}"); - } - - symlink(realpath("{$new_release->release_dir}"), "{$current}"); - - // Update manifest - $release = new \stdClass(); - $release->time = $new_release->time; - $release->number = $new_release->number; - $release->deployed_commit = $new_release->deployed_commit; - - $this->releases_manifest[] = $release; - $this->save_releases_manifest(); - } - } catch (\Exception $e) { - echo $e->getMessage(); - - exit(1); - } - - // - // Delete old deploys - // - // This is a bit hacky. I would like to use the data from the releases manifest for this, but the moving around - // of directories on -f kinda screws that up. It needs to be made better, and then we can do this properly. - // - - $releases = glob(realpath("{$this->releases_dir}").'/*', GLOB_ONLYDIR); - uasort($releases, function ($a, $b) { - return filemtime($b) - filemtime($a); - }); - - foreach (array_slice($releases, $keep) as $dir) { - $this->recurse_rmdir($dir); - } - } - - protected function load_releases_manifest() - { - $releases_manifest_file = "{$this->deploy_dir}/releases/manifest.json"; - - if (!file_exists($releases_manifest_file)) { - $this->releases_manifest = []; - } else { - $this->releases_manifest = json_decode(file_get_contents($releases_manifest_file)); - } - - // TODO: handle invalid json properly - // http://www.php.net/manual/en/function.json-last-error.php - if (!is_array($this->releases_manifest)) { - echo 'Unable to parse releases manifest'; - exit(1); - } - } - - protected function save_releases_manifest() - { - return file_put_contents("{$this->deploy_dir}/releases/manifest.json", json_encode($this->releases_manifest, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES)); - } -}; diff --git a/src/Modules/Generate.php b/src/Modules/Generate.php deleted file mode 100644 index 624918fb..00000000 --- a/src/Modules/Generate.php +++ /dev/null @@ -1,71 +0,0 @@ -generators_dir = WHIPPET_ROOT.'/generators'; - } - - public function start($thing, $options) - { - if ($thing) { - $this->generate($thing, $options); - } else { - if (isset($options->list)) { - $this->list_generators(); - } - } - } - - public function generate($thing, $options) - { - $generator_file = "{$this->generators_dir}/{$thing}/generate.php"; - - if (!file_exists($generator_file)) { - echo "Could not find a generator for {$thing}\n"; - exit(1); - } - - require $generator_file; - $generator_class = ucfirst($thing).'Generator'; - - return (new $generator_class($options))->generate(); - } - - public function list_generators() - { - echo "Available generators:\n\n"; - foreach (array_keys($this->get_generators()) as $generator) { - echo strval($generator) . "\n"; - } - } - - public function get_generators() - { - $generators = []; - - foreach (new \DirectoryIterator($this->generators_dir) as $file) { - if ($file->isDot()) { - continue; - } - - if ($file->isDir()) { - $generator_file = $this->generators_dir.'/'.$file->getFilename().'/generate.php'; - - if (file_exists($generator_file)) { - $generators[ucfirst($file->getFilename())] = $generator_file; - } - } - } - - return $generators; - } -}; diff --git a/src/Modules/Helpers/ManifestIo.php b/src/Modules/Helpers/ManifestIo.php deleted file mode 100644 index eb0fc84a..00000000 --- a/src/Modules/Helpers/ManifestIo.php +++ /dev/null @@ -1,148 +0,0 @@ -plugins_manifest. - */ - protected function load_plugins_manifest() - { - // Check for #-comments - $raw_file = file_get_contents($this->plugins_manifest_file); - $lines = explode("\n", $raw_file); - foreach ($lines as $line) { - if (preg_match('/^\s*#/', $line)) { - echo "Comments beginning with # are not permitted\n"; - exit(1); - } - } - - $plugins = parse_ini_file($this->plugins_manifest_file); - - if (!is_array($plugins)) { - echo 'Unable to parse Plugins file'; - exit(1); - } - - // Got plugins - turn names to sources - $source = $append = ''; - $this->plugins_manifest = new \stdClass(); - - foreach ($plugins as $plugin => $data) { - // - // Special lines - // - - if ($plugin == 'source') { - if (empty($data)) { - echo "Source is empty. It should just specify a repo root:\n\n source = 'git@github.com:dxw-wordpress-plugins/'\n\nWhippet will attempt to find a source for your plugins by appending the plugin name to this URL."; - exit(1); - } - - $source = $data; - continue; - } - - if ($plugin == 'append') { - $append = $data; - continue; - } - - $repository = $revision = ''; - - // - // Everything else should be a plugin - // - - // First see if there is data. - if (!empty($data)) { - // Format: LABEL[, REPO] - if (strpos($data, ',') !== false) { - list($revision, $repository) = explode(',', $data); - } else { - $revision = $data; - } - } - - if (empty($repository)) { - $repository = "{$source}{$plugin}{$append}"; - } - - if (empty($revision)) { - $revision = 'master'; - } - - // We should now have repo and revision - $this->plugins_manifest->$plugin = new \stdClass(); - $this->plugins_manifest->$plugin->repository = $repository; - $this->plugins_manifest->$plugin->revision = $revision; - } - } - - /** - * Loads the current app's plugins.lock into $this->plugins_locked. - */ - protected function load_plugins_lock() - { - if (!$this->plugins_lock_file) { - return false; - } - - $this->plugins_locked = json_decode(file_get_contents($this->plugins_lock_file)); - - // TODO: handle invalid json properly - // http://www.php.net/manual/en/function.json-last-error.php - if (!is_object($this->plugins_locked)) { - echo 'Unable to parse plugins.lock'; - exit(1); - } - } - - /** - * Updates plugins.lock based on the contents of the current plugins manifest. - * - * This method works because $this->plugins_manifest is updated as Whippet carries out plugin installations, updates and deletions. - */ - private function update_plugins_lock() - { - if (!empty($this->plugins_locked)) { - $this->old_plugins_locked = $this->plugins_locked; - } - - $this->plugins_lock_file = "{$this->project_dir}/plugins.lock"; - - $this->plugins_locked = new \stdClass(); - - /** - * @psalm-suppress UndefinedThisPropertyFetch - */ - foreach (scandir($this->plugin_dir) as $dir) { - if ($dir[0] == '.') { - continue; - } - - if (!isset($this->plugins_manifest->$dir)) { - continue; - } - - $git = new \Dxw\Whippet\Git\Git("{$this->plugin_dir}/{$dir}"); - - if (!$commit = $git->current_commit()) { - echo "Unable to determine current commit; aborting\n"; - exit(1); - } - - $this->plugins_locked->$dir = new \stdClass(); - $this->plugins_locked->$dir->repository = $this->plugins_manifest->$dir->repository; - $this->plugins_locked->$dir->revision = $this->plugins_manifest->$dir->revision; - $this->plugins_locked->$dir->commit = $commit; - } - - return file_put_contents($this->plugins_lock_file, json_encode($this->plugins_locked, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES)); - } -}; diff --git a/src/Modules/Helpers/WhippetHelpers.php b/src/Modules/Helpers/WhippetHelpers.php deleted file mode 100644 index e27a14ef..00000000 --- a/src/Modules/Helpers/WhippetHelpers.php +++ /dev/null @@ -1,223 +0,0 @@ -valid()) { - throw new \Exception("Directory exists but is not empty: {$dir}"); - } - } - } - - public function whippet_init() - { - if (!$this->plugins_manifest_file = $this->find_file('plugins')) { - if (!$this->plugins_manifest_file = $this->find_file('Plugins')) { - if (!$this->plugins_manifest_file = $this->find_file('whippet.json')) { - echo "Unable to find whippet.json or plugins manifest file\n"; - exit(1); - } - } - } - $this->project_dir = dirname($this->plugins_manifest_file); - - $this->check_for_missing_whippet_files($this->project_dir); - - $this->plugins_lock_file = $this->find_file('plugins.lock'); - $this->plugin_dir = "{$this->project_dir}/wp-content/plugins"; - - $this->load_application_config(); - } - - public function load_application_config() - { - $application_config_file = "{$this->project_dir}/config/application.json"; - - if (file_exists($application_config_file)) { - $this->application_config = json_decode(file_get_contents($application_config_file)); - - if (!is_object($this->application_config)) { - echo 'Unable to parse application config'; - exit(1); - } - } else { - $this->application_config = json_decode(' - { - "wordpress": { - "repository": "git@github.com:dxw/wordpress-snapshot", - "revision": "master" - } - } - '); - - if (file_put_contents($application_config_file, json_encode($this->application_config, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES))) { - echo "A default application.json was created\n"; - } else { - echo "No config/application.json was found, and no default could be created. Quitting.\n"; - exit(1); - } - } - } - - public function find_file($file, $include_dir = false) - { - // Starting in the current dir, walk up until we find the file - $path = getcwd(); - - do { - $file_path = $path.'/'.$file; - - if (file_exists($file_path) && ($include_dir || is_file($file_path))) { - return $file_path; - } - - $path = dirname($path); - } while ($path !== '.' && $path !== '/'); // dirname returns . or / if you call it on /, depending on platform - - return false; - } - - // 77.079482% credit: - // gimmicklessgpt@gmail.com - // http://php.net/manual/en/function.copy.php - // Modified to copy symlinks - public function recurse_copy($src, $dst) - { - $dir = opendir($src); - if (!is_dir($dst) && !is_link($dst)) { - mkdir($dst); - } - while (false !== ($file = readdir($dir))) { - if (($file != '.') && ($file != '..')) { - if (is_link($src.'/'.$file)) { - symlink(readlink($src.'/'.$file), $dst.'/'.$file); - } elseif (is_dir($src.'/'.$file)) { - $this->recurse_copy($src.'/'.$file, $dst.'/'.$file); - } else { - copy($src.'/'.$file, $dst.'/'.$file); - } - } - } - closedir($dir); - } - - // 100% credit: - // The suckiness of PHP - public function recurse_rmdir($dir) - { - $dir_handle = opendir($dir); - while (false !== ($file = readdir($dir_handle))) { - if (($file != '.') && ($file != '..')) { - if (is_link($dir.'/'.$file)) { - unlink($dir.'/'.$file); - } elseif (is_dir($dir.'/'.$file)) { - $this->recurse_rmdir($dir.'/'.$file); - } else { - unlink($dir.'/'.$file); - } - } - } - rmdir($dir); - } - - public function recurse_rm($path) - { - if (!file_exists($path)) { - return; - } - - if (is_dir($path)) { - $this->recurse_rmdir($path); - } else { - unlink($path); - } - } - - private function check_for_missing_whippet_files($project_dir) - { - $whippet_files = [ - 'config/', - 'wp-content/', - 'wp-content/plugins/', - '.gitignore', - ]; - - $missing = []; - foreach ($whippet_files as $file) { - if (!file_exists("{$project_dir}/{$file}")) { - $missing[] = $file; - } - } - - if (count($missing) > 0) { - echo "The following files and directories are required but could not be found:\n"; - foreach ($missing as $file) { - echo " {$file}\n"; - } - exit(1); - } - } - - public function find_and_replace($dir, $find, $replaceWith) - { - $files = $this->recurse_file_search($dir); - foreach ($files as $filename) { - if (is_file($filename) && is_writable($filename)) { - $file = file_get_contents($filename); - file_put_contents($filename, str_replace($find, $replaceWith, $file)); - } - } - } - - public function recurse_file_search($dir) - { - $recursive_iterator = new \RecursiveIteratorIterator(new \RecursiveDirectoryIterator($dir)); - $files = []; - foreach ($recursive_iterator as $file) { - if ($file->isDir()) { - continue; - } - $files[] = $file->getPathname(); - } - return $files; - } - - public function download_url_to_file($url, $dest) - { - $ch = curl_init(); - curl_setopt($ch, CURLOPT_URL, $url); - curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true); - curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); - $data = curl_exec($ch); - curl_close($ch); - $file = fopen($dest, "w+"); - fputs($file, $data); - fclose($file); - } - - public function unzip_to_folder($zip_file, $dest) - { - $zip = new \ZipArchive(); - $res = $zip->open($zip_file); - if ($res === true) { - $zip->extractTo($dest); // directory to extract contents to - $zip->close(); - unlink($zip_file); - } else { - echo "Unzip failed \n, error code: " . $res; - } - } -}; diff --git a/src/Modules/Plugin.php b/src/Modules/Plugin.php deleted file mode 100644 index bf3df6d5..00000000 --- a/src/Modules/Plugin.php +++ /dev/null @@ -1,304 +0,0 @@ -command('install', 'Deploys the current set of plugins into your project'); - $this->command('upgrade [PLUGIN]', 'Upgrades PLUGIN to the most recent available version, or to the version specified in your Plugin file.'); - } - - private function deprecationNotice($internal) - { - if ($internal) { - $this->warningText([ - 'Notice: Using a deprecated `plugins` file.', - ]); - } else { - $this->warningText([ - 'The plugins subcommand is deprecated and will be removed in a future release.', - '', - 'Once you have a `whippet.json` file, you can run the following instead of `whippet plugins upgrade`:', - ' $ whippet deps update', - '', - 'And the following instead of `whippet plugins install`:', - ' $ whippet deps install', - '', - '', - ]); - } - } - - private function warningText($lines) - { - $c = new \Colors\Color(); - echo $c(implode("\n", $lines))->bg('red')->fg('white')."\n"; - } - - /* - * Commands - */ - - /* - * Adds new plugins that are missing, removes old plugins that have been removed, and - * checks that plugins are on the revision referred to in the Plugins file. - * - * This command will not change an installed commit unless the revision has changed. It - * just makes sure that what's in the project is what's in the file. - */ - public function install($internal = false) - { - $this->deprecationNotice($internal); - $this->whippet_init(); - $this->load_plugins_manifest(); - $this->load_plugins_lock(); - - if (count(get_object_vars($this->plugins_manifest)) == 0) { - echo "The plugin manifest file is empty\n"; - } - - // - // If there is no lock file: - // - // 1. Install everything from the manifest - // 2. Update the lockfile - // - - if (!$this->plugins_lock_file) { - foreach ($this->plugins_manifest as $dir => $plugin) { - $git = new \Dxw\Whippet\Git\Git("{$this->plugin_dir}/{$dir}"); - - // Is the repo there already? - if (!$git->is_repo()) { - echo "[Adding {$dir}] "; - // We don't have the repo. Clone it. - if (!$git->clone_repo($plugin->repository)) { - echo "Aborting...\n"; - die(); - } - } - - // Make sure repo is up to date. - echo "[Checking {$dir}] "; - if (!$git->checkout($plugin->revision)) { - echo "Aborting...\n"; - die(); - } - - $git->checkout($git->current_commit()); - if (!$git->submodule_update()) { - echo "Aborting...\n"; - die(); - } - } - } else { - - // - // If there is a lock file: - // - // 1. Compare the lockfile to the manifest. Delete any plugins that have been removed. - // 2. Check that the installed plugins are on the lockfile commit. Checkout the correct commit if not. - // 3. Compare the lockfile to the manifest. Clone any plugins that have been added. - // 4. Update the lockfile with the new list of commits. - - // - // 1. Compare the lockfile to the manifest. Delete any plugins that have been removed. - // - - // Make sure every entry in the lockfile also appears in the manifest - $plugins_to_delete = array_keys((array) $this->plugins_locked); - - foreach (array_keys($this->plugins_locked) as $lock_dir) { - foreach (array_keys($this->plugins_manifest) as $manifest_dir) { - if ($lock_dir == $manifest_dir) { - unset($plugins_to_delete[array_search($lock_dir, $plugins_to_delete)]); - } - } - } - - // Delete the ones that don't: - $gitignore = new \Dxw\Whippet\Git\Gitignore($this->project_dir); - $ignores = $gitignore->get_ignores(); - - foreach ($plugins_to_delete as $dir) { - echo "[Removing {$dir}]\n"; - $git = new \Dxw\Whippet\Git\Git("{$this->plugin_dir}/{$dir}"); - $git->delete_repo(); - - // remove from ignores: - $plugin_dir = "/wp-content/plugins/{$dir}\n"; - - if (($index = array_search($plugin_dir, $ignores)) !== false) { - unset($ignores[$index]); - } - - // Remove from the lockfile - unset($this->plugins_locked->$dir); - } - - $gitignore->save_ignores($ignores); - - // - // 2. Check that the installed plugins are on the lockfile commit. Checkout the correct commit if not. - // - - foreach ($this->plugins_locked as $dir => $plugin) { - $git = new \Dxw\Whippet\Git\Git("{$this->plugin_dir}/{$dir}"); - - if (!$git->is_repo()) { - // The repo has gone missing. Let's add it back. - echo "[Adding {$dir}] "; - $git->clone_repo($plugin->repository); - } - - if ($this->plugins_manifest->$dir->repository != $plugin->repository) { - // The remote has changed. Zap the plugin and add it again. - $git->delete_repo(); - - // The repo should be re-added below when we add new plugins - continue; - } - - // Check out a new revision, or if no new revision, check the existing one out again (in case of naughty changes) - if ($this->plugins_manifest->$dir->revision == $plugin->revision) { - echo "[Checking {$dir}] "; - $git->checkout($plugin->commit); - } else { - echo "[Updating {$dir}] "; - $git->checkout($this->plugins_manifest->$dir->revision); - } - - if (!$git->submodule_update()) { - echo "Aborting...\n"; - die(); - } - } - - // - // 3. Compare the lockfile to the manifest. Clone any plugins that have been added. - // - - // Make sure every entry in the lockfile also appears in the manifest - $plugins_to_clone = array_keys((array) $this->plugins_manifest); - - foreach ($this->plugins_manifest as $manifest_dir => $manifest_plugin) { - foreach ($this->plugins_locked as $lock_dir => $lock_plugin) { - if ($lock_dir == $manifest_dir && $manifest_plugin->repository == $lock_plugin->repository) { - unset($plugins_to_clone[array_search($manifest_dir, $plugins_to_clone)]); - } - } - } - - foreach ($plugins_to_clone as $dir) { - $plugin = $this->plugins_manifest->$dir; - - echo "[Adding {$dir}] "; - - $git = new \Dxw\Whippet\Git\Git("{$this->plugin_dir}/{$dir}"); - - // Is the repo there already? - if (!$git->is_repo()) { - // We don't have the repo. Clone it. - if (!$git->clone_repo($plugin->repository)) { - echo "Aborting...\n"; - die(); - } - } - - // Make sure repo is up to date. - if (!$git->checkout($plugin->revision)) { - echo "Aborting...\n"; - die(); - } - - if (!$git->submodule_update()) { - echo "Aborting...\n"; - die(); - } - } - } - - // - // Update the lockfile - // - - $this->update_plugins_lock(); - - // - // Make sure that Whippet-managed plugins are gitignored - // - $gitignore = new \Dxw\Whippet\Git\Gitignore($this->project_dir); - $ignores = $gitignore->get_ignores(); - - foreach (array_keys(get_object_vars($this->plugins_locked)) as $dir) { - $plugin_dir = "/wp-content/plugins/" . strval($dir) . "\n"; - - if (array_search($plugin_dir, $ignores) === false) { - $ignores[] = $plugin_dir; - } - } - - $gitignore->save_ignores($ignores); - - echo "Completed successfully\n"; - - return \Result\Result::ok(); - } - - /* - * Checks the named plugin against the remote to see if the remote is on - * a newer commit, and checks out the newer commit if so. - */ - public function upgrade($upgrade_plugin = '') - { - $this->deprecationNotice(true); - $this->whippet_init(); - $this->load_plugins_manifest(); - $this->load_plugins_lock(); - - // - // 1. Find the plugin we're going to update. - // 2. Check it out - // 3. Update the lockfile - // - - foreach ($this->plugins_manifest as $dir => $plugin) { - - // Upgrade the plugin if: - // - It is the plugin they asked for - // - They didn't specify a plugin, and this plugin is in the manifest. - if ($dir == $upgrade_plugin || ($upgrade_plugin == '' && isset($this->plugins_manifest->$dir))) { - $git = new \Dxw\Whippet\Git\Git("{$this->plugin_dir}/{$dir}"); - - // Find the specified revision. - echo "[Checking {$dir}] "; - $git->fetch(); - - // Check it out - if (!$git->checkout($git->remote_revision_commit($plugin->revision))) { - die(); - } - - if (!$git->submodule_update()) { - die(); - } - - // If we were upgrading a specific plugin, bail now - if ($upgrade_plugin != '') { - break; - } - } - } - - $this->update_plugins_lock(); - } -}; diff --git a/src/Modules/Release.php b/src/Modules/Release.php deleted file mode 100644 index 1b78c2aa..00000000 --- a/src/Modules/Release.php +++ /dev/null @@ -1,165 +0,0 @@ -whippet_init(); - $this->load_plugins_lock(); - - $git = new \Dxw\Whippet\Git\Git($this->project_dir); - - $this->number = $number; - $this->time = date('r'); - $this->deployed_commit = $git->current_commit(); - $this->release_dir = "{$releases_dir}/{$this->deployed_commit}"; - $this->public_dir = $public_dir; - } - - public function create(&$force, &$deploy_public) - { - // - // Does this commit have a release directory already? If so, do nothing - // - - if (!$force && file_exists($this->release_dir)) { - return false; - } - - // there's no point in forcing a non-existant release - if ($force && !file_exists($this->release_dir)) { - $force = false; - } - - // Got whippet.{json,lock} or plugins.lock? - if (is_file($this->project_dir.'/whippet.json') && is_file($this->project_dir.'/whippet.lock')) { - $factory = new \Dxw\Whippet\Factory(); - $installer = new \Dxw\Whippet\Dependencies\Installer( - $factory, - new \Dxw\Whippet\ProjectDirectory($this->project_dir), - new \Dxw\Whippet\Services\NullInspectionChecker() - ); - } elseif ($this->plugins_lock_file && file_exists($this->plugins_lock_file)) { - $installer = new Plugin(); - } else { - echo "Couldn't find plugins.lock in the project directory. (Did you run whippet plugins install?)\n"; - die(1); - } - - // - // If we're here, we must deploy - // - - // 1. Clone WP - // 2. Delete wp-content etc - // 3. Make sure wp-content is up to date - // 4. Copy our wp-content, omitting gitfoo - // 5. ?? Theme/plugin build steps ?? (Makefile-esque thing?) - // 6. Symlink required files from shared dir - - // Assuming we're not forcing, create a new directory for this release, or use only an empty existing dir - if (!$force) { - $this->check_and_create_dir($this->release_dir, true); - } else { - $this->release_dir = dirname($this->release_dir).'/forced_release_tmp_'.sha1(microtime()); - } - - // Clone WP and remove things we don't want - $wp = new \Dxw\Whippet\Git\Git($this->release_dir); - $wp->clone_repo($this->application_config->wordpress->repository); - $wp->checkout($this->application_config->wordpress->revision); - - foreach (['wp-content', '.git'] as $delete) { - if (is_dir("{$this->release_dir}/$delete")) { - $this->recurse_rmdir("{$this->release_dir}/$delete"); - } else { - unlink("{$this->release_dir}/$delete"); - } - } - - // Make sure wp-content is up to date - $result = $installer->installAll(); - if ($result->isErr()) { - echo sprintf("ERROR: %s\n", $result->getErr()); - exit(1); - } - - // Copy over wp-content - $this->recurse_copy("{$this->project_dir}/wp-content", "{$this->release_dir}/wp-content"); - - if (file_exists("{$this->release_dir}/wp-content/uploads")) { - $this->recurse_rm("{$this->release_dir}/wp-content/uploads"); - } - - // - // Remove unwanted git/test foo - // - - $plugins = scandir("{$this->release_dir}/wp-content/plugins"); - foreach ($plugins as $dir) { - $path = "{$this->release_dir}/wp-content/plugins/{$dir}"; - if ($dir === '.' || $dir === '..' || !is_dir($path)) { - continue; - } - - // Remove git files from all plugins - - foreach (['.git', '.gitmodules', '.gitignore'] as $delete) { - $this->recurse_rm("{$this->release_dir}/wp-content/plugins/$dir/{$delete}"); - } - - // Remove test files from whippet plugins - - if ($this->is_whippet_plugin($path)) { - foreach (['tests', 'Makefile', '.drone.yml'] as $delete) { - $this->recurse_rm("{$this->release_dir}/wp-content/plugins/$dir/{$delete}"); - } - } - } - - // - // Deploy public assets or copy them into the app directory - // - if (is_dir("{$this->project_dir}/public")) { - $public_dest = $deploy_public ? $this->public_dir : $this->release_dir; - $this->recurse_copy("{$this->project_dir}/public", "{$public_dest}"); - } - - // - // TODO: theme and plugin build steps - // - - // Symlinkery - symlink(realpath("{$this->release_dir}/../../shared/wp-config.php"), "{$this->release_dir}/wp-config.php"); - symlink(realpath("{$this->release_dir}/../../shared/uploads"), "{$this->release_dir}/wp-content/uploads"); - - // FIN - } - - public function is_whippet_plugin($path) - { - $files = glob($path.'/*.php'); - foreach ($files as $file) { - if (is_file($file)) { - //TODO: This is probably okay in most cases but if we come across a 1GB .php file PHP might run out of memory - $f = file_get_contents($file); - if (strpos($f, 'Whippet: yes') !== false) { - return true; - } - } - } - - return false; - } -}; diff --git a/src/Modules/Theme.php b/src/Modules/Theme.php deleted file mode 100644 index e7ceecc0..00000000 --- a/src/Modules/Theme.php +++ /dev/null @@ -1,56 +0,0 @@ -command('grunt *arguments', 'Runs the specified grunt command in the context of your theme');/*, function($option_parser) { - $option_parser->addRule('t|theme::', "Specify theme. Default: the theme directory you're in"); - });*/ - } - - /* - * Commands - */ - - /* - * Runs the specified Grunt commands with the necessary arguments to make everything work with NPM and grunt in /vendor - */ - public function grunt($args) - { - $grunt_commands = $args; - - // Look for the theme base - if (!isset($this->options->theme)) { - if (!$vendor = $this->find_file('vendor', true)) { - echo "Unable to find the theme's vendor directory\n"; - exit(1); - } - - if (!isset($this->options)) { - $this->options = new \stdClass(); - } - - $this->options->theme = dirname($vendor); - } else { - if (!file_exists($this->options->theme)) { - echo "Specified theme directory not found\n"; - exit(1); - } - } - - // Sanity checks on contents of vendor - if (!file_exists("{$this->options->theme}/vendor/Gruntfile.js") || !file_exists("{$this->options->theme}/vendor/package.json")) { - echo "Found a theme at {$this->options->theme}, but its vendor directory doesn't look valid (no package.json or Gruntfile.js)\n"; - exit(1); - } - - $this->options->theme = realpath($this->options->theme); - - system("grunt --base {$this->options->theme}/vendor --gruntfile {$this->options->theme}/vendor/Gruntfile.js {$grunt_commands}\n"); - } -}; diff --git a/src/ProjectDirectory.php b/src/ProjectDirectory.php deleted file mode 100644 index d49885ab..00000000 --- a/src/ProjectDirectory.php +++ /dev/null @@ -1,33 +0,0 @@ -path = $path; - } - - #[\ReturnTypeWillChange] - public function __toString() - { - return $this->path; - } -} diff --git a/src/Services/BaseApi.php b/src/Services/BaseApi.php deleted file mode 100644 index 0f715223..00000000 --- a/src/Services/BaseApi.php +++ /dev/null @@ -1,29 +0,0 @@ -client = new \GuzzleHttp\Client([ - 'headers' => [ 'User-Agent' => 'Whippet https://github.com/dxw/whippet/' ] - ]); - } - - public function get($url) - { - try { - $response = $this->client->get($url); - } catch (\GuzzleHttp\Exception\ConnectException $e) { - return \Result\Result::err('Failed to connect to '.$url); - } catch (\GuzzleHttp\Exception\RequestException $e) { - return \Result\Result::err('Failed to receive data from '.$url); - } - - return \Result\Result::ok($response->getBody()); - } -} diff --git a/src/Services/InspectionChecker.php b/src/Services/InspectionChecker.php deleted file mode 100644 index cb8f0952..00000000 --- a/src/Services/InspectionChecker.php +++ /dev/null @@ -1,67 +0,0 @@ -inspectionsApi = $inspections_api; - } - - public function check($type, $dependency) - { - switch ($type) { - case 'themes': - return \Result\Result::ok(''); - case 'plugins': - return $this->checkPlugin($dependency); - default: - return \Result\Result::err("Unknown type '".$type."'"); - } - } - - private function checkPlugin($dependency) - { - $result = $this->inspectionsApi->getInspections($dependency['name']); - - if ($result->isErr()) { - return \Result\Result::err("Error fetching plugin inspections from API: '".$result->getErr()."'"); - } - - $inspections = $result->unwrap(); - if (empty($inspections)) { - $warning_msg = <<<'EOT' -############################################# -# # -# WARNING: No inspections for this plugin # -# # -############################################# -EOT; - return \Result\Result::ok($warning_msg); - } else { - return \Result\Result::ok($this->inspectionsMessage($inspections)); - } - } - - private function inspectionsMessage($inspections) - { - $lines = []; - $lines[] = "Inspections for this plugin:"; - foreach ($inspections as $inspection) { - $lines[] = $this->formatInspection($inspection); - } - return implode("\n", $lines); - } - - private function formatInspection($inspection) - { - $date = date_format($inspection->date, 'd/m/Y'); - return sprintf("* %s - %s - %s - %s", $date, $inspection->versions, $inspection->result, $inspection->url); - } -} diff --git a/src/Services/InspectionsApi.php b/src/Services/InspectionsApi.php deleted file mode 100644 index fd62a252..00000000 --- a/src/Services/InspectionsApi.php +++ /dev/null @@ -1,87 +0,0 @@ -host = $host; - $this->path = $path; - $this->jsonApi = $json_api; - } - - public function getInspections($plugin_slug) - { - $result = $this->jsonApi->get($this->url($plugin_slug)); - if ($result->isErr()) { - return $result; - } - $inspections_data = $result->unwrap(); - if (!$this->validateInspections($inspections_data)) { - return \Result\Result::err("Couldn't extract inspections from JSON response"); - } - $inspections = $this->buildInspections($inspections_data); - return \Result\Result::ok($inspections); - } - - private function buildInspections($raw_inspections) - { - return array_map(function ($raw_inspection) { - return new Inspection( - $raw_inspection['date'], - $raw_inspection['versions'], - $raw_inspection['result'], - $raw_inspection['url'] - ); - }, $raw_inspections); - } - - private function validateInspections($raw_inspections) - { - if (!is_array($raw_inspections)) { - return false; - } - - foreach ($raw_inspections as $raw_inspection) { - if (!$this->validateInspection($raw_inspection)) { - return false; - } - } - - return true; - } - - private function validateInspection($raw_inspection) - { - $keys = [ - 'date', - 'versions', - 'result', - 'url', - ]; - - foreach ($keys as $key) { - if (!array_key_exists($key, $raw_inspection)) { - return false; - } - } - return true; - } - - private function url($plugin_slug) - { - return $this->host.$this->path.$plugin_slug; - } -} diff --git a/src/Services/JsonApi.php b/src/Services/JsonApi.php deleted file mode 100644 index 3893e007..00000000 --- a/src/Services/JsonApi.php +++ /dev/null @@ -1,33 +0,0 @@ -baseApi = $base_api; - } - - public function get($url) - { - $response = $this->baseApi->get($url); - - if ($response->isErr()) { - return $response; - } - - $response_as_array = json_decode($response->unwrap(), true); - if (is_null($response_as_array)) { - return \Result\Result::err('Failed to parse response body as JSON when requesting '.$url); - } - return \Result\Result::ok($response_as_array); - } -} diff --git a/src/Services/NullInspectionChecker.php b/src/Services/NullInspectionChecker.php deleted file mode 100644 index 74728a29..00000000 --- a/src/Services/NullInspectionChecker.php +++ /dev/null @@ -1,12 +0,0 @@ -command('plugins PLUGIN_COMMAND', ''); - $this->command('theme THEME_COMMAND', ''); - - $this->command('deploy DIR', "Generates a working WordPress installation in DIR, based on the current contents of your app's repository", function ($option_parser) { - $option_parser->addRule('f|force', 'Force Whippet to deploy, even if a release already exists for this commit'); - $option_parser->addRule('k|keep::', 'Tells Whippet how many old release directories to keep. Default: 3'); - $option_parser->addRule('p|public::', 'Deploy public/ in a given directory, adjacent to the app'); - }); - - $this->command('generate [THING]', 'Generates a thing', function ($option_parser) { - $option_parser->addRule('l|list', 'Lists available generators'); - $option_parser->addRule('d|directory::', "Override the generator's default creation directory with this one"); - $option_parser->addRule('n|nogitignore', 'When generating a theme, do not generate the accompanying .gitignore file'); - $option_parser->addRule('r|repository::', 'When generating an app, override the default application.json WordPress repository with this one'); - }); - - $this->command('init [PATH]', 'Creates a new Whippet application at PATH. NB: this is a shortcut for whippet generate -d PATH whippet.', function ($option_parser) { - $option_parser->addRule('r|repository::', 'Override the default application.json WordPress repository with this one'); - }); - $this->command('dependencies SUBCOMMAND', 'Manage dependencies (themes, plugins)'); - $this->command('deps SUBCOMMAND', 'Alias for dependencies'); - } - - public function plugins() - { - (new Modules\Plugin())->start(array_slice($this->argv, 1)); - } - - public function theme() - { - (new Modules\Theme())->start(array_slice($this->argv, 1)); - } - - public function deploy($dir) - { - if (!isset($this->options->keep)) { - $this->options->keep = 3; - } - - if (!isset($this->options->public)) { - $this->options->public = ""; - } - - (new Modules\Deploy($dir))->deploy( - isset($this->options->force), - $this->options->keep, - $this->options->public - ); - } - - public function init($path = false) - { - if ($path) { - $this->options->directory = $path; - } - - (new Modules\Generate())->start('app', $this->options); - } - - public function generate($thing = false) - { - (new Modules\Generate())->start($thing, $this->options); - } - - public function dependencies() - { - (new Modules\Dependencies())->start(array_slice($this->argv, 1)); - } - - public function deps() - { - $this->dependencies(); - } -}; diff --git a/src/WhippetGenerator.php b/src/WhippetGenerator.php deleted file mode 100644 index 4c84836d..00000000 --- a/src/WhippetGenerator.php +++ /dev/null @@ -1,21 +0,0 @@ -factoryNewInstance = []; - $this->factoryCallStatic = []; - } - - private function getWhippetLock(/* string */ $hash, array $dependencyMap) - { - $whippetLock = $this->getMockBuilder('\\Dxw\\Whippet\\Files\\WhippetLock') - ->disableOriginalConstructor() - ->getMock(); - - $whippetLock->method('getHash') - ->willReturn($hash); - - $map = []; - foreach ($dependencyMap as $dependencyType => $return) { - $map[] = [$dependencyType, $return]; - } - - $whippetLock->method('getDependencies') - ->will($this->returnValueMap($map)); - - return $whippetLock; - } - - private function getArchivedWarning() - { - $warning = <<<'EOT' -!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -!! WARNING: GitHub repo is archived. This dependency !! -!! should be replaced before the repo is removed. !! -!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! - -EOT; - return $warning; - } - - private function getGit($isRepo, $cloneRepo, $checkout, $isArchived = false) - { - $archived_warning = $this->getArchivedWarning(); - - $git = $this->getMockBuilder('\\Dxw\\Whippet\\Git\\Git') - ->disableOriginalConstructor() - ->getMock(); - - $git->method('is_repo') - ->willReturn($isRepo); - - if ($cloneRepo !== null) { - $return = true; - $output = "git clone output\n"; - - if ($isArchived) { - $output = $archived_warning . $output; - } - - if (is_array($cloneRepo)) { - $return = $cloneRepo['return']; - $cloneRepo = $cloneRepo['with']; - } - - $git->expects($this->exactly(1)) - ->method('clone_repo') - ->with($cloneRepo) - ->will($this->returnCallback(function () use ($output, $return) { - echo $output; - - return $return; - })); - } - - if ($checkout !== null) { - $return = true; - $output = "git checkout output\n"; - - if ($isArchived) { - $output = $archived_warning . $output; - } - - if (is_array($checkout)) { - $return = $checkout['return']; - $checkout = $checkout['with']; - } - - $git->expects($this->exactly(1)) - ->method('checkout') - ->with($checkout) - ->will($this->returnCallback(function () use ($output, $return) { - echo $output; - - return $return; - })); - } - - return $git; - } - - private function getWhippetJson(array $data) - { - return new \Dxw\Whippet\Files\WhippetJson($data); - } - - private function getFactory() - { - $factory = $this->getMockBuilder('\\Dxw\\Whippet\\Factory') - ->disableOriginalConstructor() - ->getMock(); - - $factory->method('newInstance') - ->will($this->returnValueMap($this->factoryNewInstance)); - - $factory->method('callStatic') - ->will($this->returnValueMap($this->factoryCallStatic)); - - return $factory; - } - - private function addFactoryNewInstance() - { - $this->factoryNewInstance[] = func_get_args(); - } - - private function addFactoryCallStatic() - { - $this->factoryCallStatic[] = func_get_args(); - } - - private function getProjectDirectory($dir) - { - return new \Dxw\Whippet\ProjectDirectory($dir); - } - - private function getDir() - { - $root = \org\bovigo\vfs\vfsStream::setup(); - - return $root->url(); - } -} diff --git a/tests/dependencies/installer_test.php b/tests/dependencies/installer_test.php deleted file mode 100644 index 0009ccf0..00000000 --- a/tests/dependencies/installer_test.php +++ /dev/null @@ -1,678 +0,0 @@ -getDir(); - file_put_contents($dir.'/whippet.json', 'foobar'); - file_put_contents($dir.'/whippet.lock', 'foobar'); - - $my_theme = [ - 'name' => 'my-theme', - 'src' => 'git@github.com:dxw-wordpress-themes/my-theme', - 'revision' => '27ba906', - ]; - - $my_plugin = [ - 'name' => 'my-plugin', - 'src' => 'git@github.com:dxw-wordpress-plugins/my-plugin', - 'revision' => '123456', - ]; - - $another_plugin = [ - 'name' => 'another-plugin', - 'src' => 'git@github.com:dxw-wordpress-plugins/another-plugin', - 'revision' => '789abc', - ]; - - $whippetLock = $this->getWhippetLock(sha1('foobar'), [ - 'themes' => [ - $my_theme, - ], - 'plugins' => [ - $my_plugin, - $another_plugin, - ], - ]); - $this->addFactoryCallStatic('\\Dxw\\Whippet\\Files\\WhippetLock', 'fromFile', $dir.'/whippet.lock', \Result\Result::ok($whippetLock)); - - $gitMyTheme = $this->getGit(false, 'git@github.com:dxw-wordpress-themes/my-theme', '27ba906'); - $this->addFactoryNewInstance('\\Dxw\\Whippet\\Git\\Git', $dir.'/wp-content/themes/my-theme', $gitMyTheme); - $gitMyPlugin = $this->getGit(false, 'git@github.com:dxw-wordpress-plugins/my-plugin', '123456'); - $this->addFactoryNewInstance('\\Dxw\\Whippet\\Git\\Git', $dir.'/wp-content/plugins/my-plugin', $gitMyPlugin); - $gitAnotherPlugin = $this->getGit(false, 'git@github.com:dxw-wordpress-plugins/another-plugin', '789abc'); - $this->addFactoryNewInstance('\\Dxw\\Whippet\\Git\\Git', $dir.'/wp-content/plugins/another-plugin', $gitAnotherPlugin); - - $inspection_check_results = function ($type, $dep) { - $warning_msg = <<<'EOT' -############################################# -# # -# WARNING: No inspections for this plugin # -# # -############################################# -EOT; - - return [ - 'themes' => [ - 'my-theme' => \Result\Result::ok('') - ], - 'plugins' => [ - 'my-plugin' => \Result\Result::ok($warning_msg), - 'another-plugin' => \Result\Result::ok("Inspections for this plugin:\n* 01/05/2015 - 0.1.3 - No issues found - https://advisories.dxw.com/plugins/another_plugin/") - ] - ][$type][$dep['name']]; - }; - - $dependencies = new \Dxw\Whippet\Dependencies\Installer( - $this->getFactory(), - $this->getProjectDirectory($dir), - $this->fakeInspectionCheckerWithResults($inspection_check_results) - ); - - ob_start(); - $result = $dependencies->installAll(); - $output = ob_get_clean(); - - $this->assertFalse($result->isErr()); - $expectedOutput = <<<'EOT' -[Adding themes/my-theme] -git clone output -git checkout output - -[Adding plugins/my-plugin] -git clone output -git checkout output -############################################# -# # -# WARNING: No inspections for this plugin # -# # -############################################# - -[Adding plugins/another-plugin] -git clone output -git checkout output -Inspections for this plugin: -* 01/05/2015 - 0.1.3 - No issues found - https://advisories.dxw.com/plugins/another_plugin/ - - -EOT; - $this->assertEquals($expectedOutput, $output); - } - - public function testInspectionsApiUnavailable() - { - $dir = $this->getDir(); - file_put_contents($dir.'/whippet.json', 'foobar'); - file_put_contents($dir.'/whippet.lock', 'foobar'); - - $my_plugin = [ - 'name' => 'my-plugin', - 'src' => 'git@github.com:dxw-wordpress-plugins/my-plugin', - 'revision' => '123456', - ]; - - $whippetLock = $this->getWhippetLock(sha1('foobar'), [ - 'themes' => [], - 'plugins' => [ - $my_plugin, - ], - ]); - $this->addFactoryCallStatic('\\Dxw\\Whippet\\Files\\WhippetLock', 'fromFile', $dir.'/whippet.lock', \Result\Result::ok($whippetLock)); - - $gitMyPlugin = $this->getGit(false, 'git@github.com:dxw-wordpress-plugins/my-plugin', '123456'); - $this->addFactoryNewInstance('\\Dxw\\Whippet\\Git\\Git', $dir.'/wp-content/plugins/my-plugin', $gitMyPlugin); - - $inspection_check_results = function ($type, $dep) { - return [ - 'plugins' => [ - 'my-plugin' => \Result\Result::err('foooooo'), - ] - ][$type][$dep['name']]; - }; - - $dependencies = new \Dxw\Whippet\Dependencies\Installer( - $this->getFactory(), - $this->getProjectDirectory($dir), - $this->fakeInspectionCheckerWithResults($inspection_check_results) - ); - - ob_start(); - $result = $dependencies->installAll(); - $output = ob_get_clean(); - - $this->assertFalse($result->isErr()); - $expectedOutput = <<<'EOT' -[Adding plugins/my-plugin] -git clone output -git checkout output -[ERROR] foooooo - - -EOT; - - $this->assertEquals($expectedOutput, $output); - } - - public function testInstallArchiveRepo() - { - $dir = $this->getDir(); - file_put_contents($dir.'/whippet.json', 'foobar'); - file_put_contents($dir.'/whippet.lock', 'foobar'); - - $my_theme = [ - 'name' => 'my-theme', - 'src' => 'git@github.com:dxw-wordpress-themes/my-theme', - 'revision' => '27ba906', - ]; - - $whippetLock = $this->getWhippetLock(sha1('foobar'), [ - 'themes' => [ - $my_theme, - ], - 'plugins' => [], - ]); - $this->addFactoryCallStatic('\\Dxw\\Whippet\\Files\\WhippetLock', 'fromFile', $dir.'/whippet.lock', \Result\Result::ok($whippetLock)); - - $gitMyTheme = $this->getGit(false, 'git@github.com:dxw-wordpress-themes/my-theme', '27ba906', true); - $this->addFactoryNewInstance('\\Dxw\\Whippet\\Git\\Git', $dir.'/wp-content/themes/my-theme', $gitMyTheme); - - $inspection_check_results = function ($type, $dep) { - return [ - 'themes' => [ - 'my-theme' => \Result\Result::ok('') - ], - ][$type][$dep['name']]; - }; - - $dependencies = new \Dxw\Whippet\Dependencies\Installer( - $this->getFactory(), - $this->getProjectDirectory($dir), - $this->fakeInspectionCheckerWithResults($inspection_check_results) - ); - - ob_start(); - $result = $dependencies->installAll(); - $output = ob_get_clean(); - - $this->assertFalse($result->isErr()); - $expectedOutput = <<<'EOT' -[Adding themes/my-theme] -!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -!! WARNING: GitHub repo is archived. This dependency !! -!! should be replaced before the repo is removed. !! -!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -git clone output -!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -!! WARNING: GitHub repo is archived. This dependency !! -!! should be replaced before the repo is removed. !! -!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -git checkout output - - -EOT; - $this->assertEquals($expectedOutput, $output); - } - - public function testInstallAllThemeAlreadyCloned() - { - $dir = $this->getDir(); - file_put_contents($dir.'/whippet.json', 'foobar'); - file_put_contents($dir.'/whippet.lock', 'foobar'); - - mkdir($dir.'/wp-content/themes/my-theme'); - - $whippetLock = $this->getWhippetLock(sha1('foobar'), [ - 'themes' => [ - [ - 'name' => 'my-theme', - 'src' => 'git@github.com:dxw-wordpress-themes/my-theme', - 'revision' => '27ba906', - ], - ], - 'plugins' => [], - ]); - $this->addFactoryCallStatic('\\Dxw\\Whippet\\Files\\WhippetLock', 'fromFile', $dir.'/whippet.lock', \Result\Result::ok($whippetLock)); - - $git = $this->getGit(true, null, '27ba906'); - $this->addFactoryNewInstance('\\Dxw\\Whippet\\Git\\Git', $dir.'/wp-content/themes/my-theme', $git); - - $dependencies = new \Dxw\Whippet\Dependencies\Installer( - $this->getFactory(), - $this->getProjectDirectory($dir), - $this->fakeInspectionChecker() - ); - - ob_start(); - $result = $dependencies->installAll(); - $output = ob_get_clean(); - - $this->assertFalse($result->isErr()); - $this->assertEquals("[Checking themes/my-theme]\ngit checkout output\n\n", $output); - } - - public function testInstallAllMissingWhippetJson() - { - $dir = $this->getDir(); - - $dependencies = new \Dxw\Whippet\Dependencies\Installer( - $this->getFactory(), - $this->getProjectDirectory($dir), - $this->fakeInspectionChecker() - ); - - ob_start(); - $result = $dependencies->installAll(); - $output = ob_get_clean(); - - $this->assertEquals(true, $result->isErr()); - $this->assertEquals('whippet.json not found', $result->getErr()); - $this->assertEquals('', $output); - } - - public function testInstallAllMissingWhippetLock() - { - $dir = $this->getDir(); - file_put_contents($dir.'/whippet.json', 'foobar'); - - $this->addFactoryCallStatic('\\Dxw\\Whippet\\Files\\WhippetLock', 'fromFile', $dir.'/whippet.lock', \Result\Result::err('file not found')); - - $dependencies = new \Dxw\Whippet\Dependencies\Installer( - $this->getFactory(), - $this->getProjectDirectory($dir), - $this->fakeInspectionChecker() - ); - - ob_start(); - $result = $dependencies->installAll(); - $output = ob_get_clean(); - - $this->assertEquals(true, $result->isErr()); - $this->assertEquals('whippet.lock: file not found', $result->getErr()); - $this->assertEquals('', $output); - } - - public function testInstallAllWrongHash() - { - $dir = $this->getDir(); - file_put_contents($dir.'/whippet.json', 'foobar'); - file_put_contents($dir.'/whippet.lock', 'foobar'); - - $whippetLock = $this->getWhippetLock('123123', []); - $this->addFactoryCallStatic('\\Dxw\\Whippet\\Files\\WhippetLock', 'fromFile', $dir.'/whippet.lock', \Result\Result::ok($whippetLock)); - - $dependencies = new \Dxw\Whippet\Dependencies\Installer( - $this->getFactory(), - $this->getProjectDirectory($dir), - $this->fakeInspectionChecker() - ); - - ob_start(); - $result = $dependencies->installAll(); - $output = ob_get_clean(); - - $this->assertEquals(true, $result->isErr()); - $this->assertEquals('mismatched hash - run `whippet dependencies update` first', $result->getErr()); - $this->assertEquals('', $output); - } - - public function testInstallAllCloneFails() - { - $dir = $this->getDir(); - file_put_contents($dir.'/whippet.json', 'foobar'); - file_put_contents($dir.'/whippet.lock', 'foobar'); - - $whippetLock = $this->getWhippetLock(sha1('foobar'), [ - 'themes' => [ - [ - 'name' => 'my-theme', - 'src' => 'git@github.com:dxw-wordpress-themes/my-theme', - 'revision' => '27ba906', - ], - ], - 'plugins' => [], - ]); - $this->addFactoryCallStatic('\\Dxw\\Whippet\\Files\\WhippetLock', 'fromFile', $dir.'/whippet.lock', \Result\Result::ok($whippetLock)); - - $gitMyTheme = $this->getGit(false, ['with' => 'git@github.com:dxw-wordpress-themes/my-theme', 'return' => false], null); - $this->addFactoryNewInstance('\\Dxw\\Whippet\\Git\\Git', $dir.'/wp-content/themes/my-theme', $gitMyTheme); - - $dependencies = new \Dxw\Whippet\Dependencies\Installer( - $this->getFactory(), - $this->getProjectDirectory($dir), - $this->fakeInspectionChecker() - ); - - ob_start(); - $result = $dependencies->installAll(); - $output = ob_get_clean(); - - $this->assertTrue($result->isErr()); - $this->assertEquals('could not clone repository', $result->getErr()); - $this->assertEquals("[Adding themes/my-theme]\ngit clone output\n", $output); - } - - public function testInstallAllCheckoutFails() - { - $dir = $this->getDir(); - file_put_contents($dir.'/whippet.json', 'foobar'); - file_put_contents($dir.'/whippet.lock', 'foobar'); - - $whippetLock = $this->getWhippetLock(sha1('foobar'), [ - 'themes' => [ - [ - 'name' => 'my-theme', - 'src' => 'git@github.com:dxw-wordpress-themes/my-theme', - 'revision' => '27ba906', - ], - ], - 'plugins' => [], - ]); - $this->addFactoryCallStatic('\\Dxw\\Whippet\\Files\\WhippetLock', 'fromFile', $dir.'/whippet.lock', \Result\Result::ok($whippetLock)); - - $gitMyTheme = $this->getGit(false, 'git@github.com:dxw-wordpress-themes/my-theme', ['with' => '27ba906', 'return' => false]); - $this->addFactoryNewInstance('\\Dxw\\Whippet\\Git\\Git', $dir.'/wp-content/themes/my-theme', $gitMyTheme); - - $dependencies = new \Dxw\Whippet\Dependencies\Installer( - $this->getFactory(), - $this->getProjectDirectory($dir), - $this->fakeInspectionChecker() - ); - - ob_start(); - $result = $dependencies->installAll(); - $output = ob_get_clean(); - - $this->assertTrue($result->isErr()); - $this->assertEquals('could not checkout revision', $result->getErr()); - $this->assertEquals("[Adding themes/my-theme]\ngit clone output\ngit checkout output\n", $output); - } - - public function testInstallAllBlankLockfile() - { - $dir = $this->getDir(); - file_put_contents($dir.'/whippet.json', 'foobar'); - file_put_contents($dir.'/whippet.lock', 'foobar'); - - $whippetLock = $this->getWhippetLock(sha1('foobar'), [ - 'themes' => [], - 'plugins' => [], - ]); - $this->addFactoryCallStatic('\\Dxw\\Whippet\\Files\\WhippetLock', 'fromFile', $dir.'/whippet.lock', \Result\Result::ok($whippetLock)); - - $dependencies = new \Dxw\Whippet\Dependencies\Installer( - $this->getFactory(), - $this->getProjectDirectory($dir), - $this->fakeInspectionChecker() - ); - - ob_start(); - $result = $dependencies->installAll(); - $output = ob_get_clean(); - - $this->assertFalse($result->isErr()); - $this->assertEquals("whippet.lock contains nothing to install\n", $output); - } - - public function testInstallSingle() - { - $dir = $this->getDir(); - file_put_contents($dir.'/whippet.json', 'foobar'); - file_put_contents($dir.'/whippet.lock', 'foobar'); - - $whippetLock = $this->getWhippetLock(sha1('foobar'), [ - 'themes' => [ - [ - 'name' => 'my-theme', - 'src' => 'git@github.com:dxw-wordpress-themes/my-theme', - 'revision' => '27ba906', - ], - ], - 'plugins' => [ - [ - 'name' => 'my-plugin', - 'src' => 'git@github.com:dxw-wordpress-plugins/my-plugin', - 'revision' => '123456', - ], - [ - 'name' => 'another-plugin', - 'src' => 'git@github.com:dxw-wordpress-plugins/another-plugin', - 'revision' => '789abc', - ], - ], - ]); - $this->addFactoryCallStatic('\\Dxw\\Whippet\\Files\\WhippetLock', 'fromFile', $dir.'/whippet.lock', \Result\Result::ok($whippetLock)); - - $gitMyPlugin = $this->getGit(true, null, '123456'); - $this->addFactoryNewInstance('\\Dxw\\Whippet\\Git\\Git', $dir.'/wp-content/plugins/my-plugin', $gitMyPlugin); - - $inspection_check_results = function ($type, $dep) { - return [ - 'plugins' => [ - 'my-plugin' => \Result\Result::ok("Inspections for this plugin:\n* 01/05/2015 - No issues found - https://advisories.dxw.com/plugins/my-plugin/") - ] - ][$type][$dep['name']]; - }; - - $dependencies = new \Dxw\Whippet\Dependencies\Installer( - $this->getFactory(), - $this->getProjectDirectory($dir), - $this->fakeInspectionCheckerWithResults($inspection_check_results) - ); - ob_start(); - $result = $dependencies->installSingle('plugins/my-plugin'); - $output = ob_get_clean(); - - $expectedOutput = <<<'EOT' -[Checking plugins/my-plugin] -git checkout output -Inspections for this plugin: -* 01/05/2015 - No issues found - https://advisories.dxw.com/plugins/my-plugin/ - - -EOT; - $this->assertEquals($expectedOutput, $output); - $this->assertFalse($result->isErr()); - } - - public function testInstallSingleAlreadyCloned() - { - $dir = $this->getDir(); - file_put_contents($dir.'/whippet.json', 'foobar'); - file_put_contents($dir.'/whippet.lock', 'foobar'); - - $whippetLock = $this->getWhippetLock(sha1('foobar'), [ - 'themes' => [ - [ - 'name' => 'my-theme', - 'src' => 'git@github.com:dxw-wordpress-themes/my-theme', - 'revision' => '27ba906', - ], - ], - 'plugins' => [ - [ - 'name' => 'my-plugin', - 'src' => 'git@github.com:dxw-wordpress-plugins/my-plugin', - 'revision' => '123456', - ], - [ - 'name' => 'another-plugin', - 'src' => 'git@github.com:dxw-wordpress-plugins/another-plugin', - 'revision' => '789abc', - ], - ], - ]); - $this->addFactoryCallStatic('\\Dxw\\Whippet\\Files\\WhippetLock', 'fromFile', $dir.'/whippet.lock', \Result\Result::ok($whippetLock)); - - $gitMyPlugin = $this->getGit(false, 'git@github.com:dxw-wordpress-plugins/my-plugin', '123456'); - $this->addFactoryNewInstance('\\Dxw\\Whippet\\Git\\Git', $dir.'/wp-content/plugins/my-plugin', $gitMyPlugin); - - $dependencies = new \Dxw\Whippet\Dependencies\Installer( - $this->getFactory(), - $this->getProjectDirectory($dir), - $this->fakeInspectionChecker() - ); - ob_start(); - $result = $dependencies->installSingle('plugins/my-plugin'); - $output = ob_get_clean(); - - $this->assertEquals("[Adding plugins/my-plugin]\ngit clone output\ngit checkout output\n\n", $output); - $this->assertFalse($result->isErr()); - } - - public function testInstallSingleAlreadyClonedAndArchived() - { - $dir = $this->getDir(); - file_put_contents($dir.'/whippet.json', 'foobar'); - file_put_contents($dir.'/whippet.lock', 'foobar'); - - $whippetLock = $this->getWhippetLock(sha1('foobar'), [ - 'themes' => [ - [ - 'name' => 'my-theme', - 'src' => 'git@github.com:dxw-wordpress-themes/my-theme', - 'revision' => '27ba906', - ], - ], - 'plugins' => [ - [ - 'name' => 'my-plugin', - 'src' => 'git@github.com:dxw-wordpress-plugins/my-plugin', - 'revision' => '123456', - ], - [ - 'name' => 'another-plugin', - 'src' => 'git@github.com:dxw-wordpress-plugins/another-plugin', - 'revision' => '789abc', - ], - ], - ]); - $this->addFactoryCallStatic('\\Dxw\\Whippet\\Files\\WhippetLock', 'fromFile', $dir.'/whippet.lock', \Result\Result::ok($whippetLock)); - - $gitMyPlugin = $this->getGit(false, 'git@github.com:dxw-wordpress-plugins/my-plugin', '123456', true); - $this->addFactoryNewInstance('\\Dxw\\Whippet\\Git\\Git', $dir.'/wp-content/plugins/my-plugin', $gitMyPlugin); - - $dependencies = new \Dxw\Whippet\Dependencies\Installer( - $this->getFactory(), - $this->getProjectDirectory($dir), - $this->fakeInspectionChecker() - ); - ob_start(); - $result = $dependencies->installSingle('plugins/my-plugin'); - $output = ob_get_clean(); - $expectedOutput = <<<'EOT' -[Adding plugins/my-plugin] -!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -!! WARNING: GitHub repo is archived. This dependency !! -!! should be replaced before the repo is removed. !! -!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -git clone output -!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -!! WARNING: GitHub repo is archived. This dependency !! -!! should be replaced before the repo is removed. !! -!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -git checkout output - - -EOT; - - - $this->assertEquals($expectedOutput, $output); - $this->assertFalse($result->isErr()); - } - - public function testInstallSingleCloneFails() - { - $dir = $this->getDir(); - file_put_contents($dir.'/whippet.json', 'foobar'); - file_put_contents($dir.'/whippet.lock', 'foobar'); - - $whippetLock = $this->getWhippetLock(sha1('foobar'), [ - 'themes' => [ - [ - 'name' => 'my-theme', - 'src' => 'git@github.com:dxw-wordpress-themes/my-theme', - 'revision' => '27ba906', - ], - ], - 'plugins' => [], - ]); - $this->addFactoryCallStatic('\\Dxw\\Whippet\\Files\\WhippetLock', 'fromFile', $dir.'/whippet.lock', \Result\Result::ok($whippetLock)); - - $gitMyTheme = $this->getGit(false, ['with' => 'git@github.com:dxw-wordpress-themes/my-theme', 'return' => false], null); - $this->addFactoryNewInstance('\\Dxw\\Whippet\\Git\\Git', $dir.'/wp-content/themes/my-theme', $gitMyTheme); - - $dependencies = new \Dxw\Whippet\Dependencies\Installer( - $this->getFactory(), - $this->getProjectDirectory($dir), - $this->fakeInspectionChecker() - ); - - ob_start(); - $result = $dependencies->installSingle('themes/my-theme'); - $output = ob_get_clean(); - - $this->assertTrue($result->isErr()); - $this->assertEquals('could not clone repository', $result->getErr()); - $this->assertEquals("[Adding themes/my-theme]\ngit clone output\n", $output); - } - - public function testInstallSingleCheckoutFails() - { - $dir = $this->getDir(); - file_put_contents($dir.'/whippet.json', 'foobar'); - file_put_contents($dir.'/whippet.lock', 'foobar'); - - $whippetLock = $this->getWhippetLock(sha1('foobar'), [ - 'themes' => [ - [ - 'name' => 'my-theme', - 'src' => 'git@github.com:dxw-wordpress-themes/my-theme', - 'revision' => '27ba906', - ], - ], - 'plugins' => [], - ]); - $this->addFactoryCallStatic('\\Dxw\\Whippet\\Files\\WhippetLock', 'fromFile', $dir.'/whippet.lock', \Result\Result::ok($whippetLock)); - - $gitMyTheme = $this->getGit(false, 'git@github.com:dxw-wordpress-themes/my-theme', ['with' => '27ba906', 'return' => false]); - $this->addFactoryNewInstance('\\Dxw\\Whippet\\Git\\Git', $dir.'/wp-content/themes/my-theme', $gitMyTheme); - - $dependencies = new \Dxw\Whippet\Dependencies\Installer( - $this->getFactory(), - $this->getProjectDirectory($dir), - $this->fakeInspectionChecker() - ); - - ob_start(); - $result = $dependencies->installSingle('themes/my-theme'); - $output = ob_get_clean(); - - $this->assertTrue($result->isErr()); - $this->assertEquals('could not checkout revision', $result->getErr()); - $this->assertEquals("[Adding themes/my-theme]\ngit clone output\ngit checkout output\n", $output); - } - - private function fakeInspectionChecker() - { - return \Mockery::mock('\\Dxw\\Whippet\\Services\\InspectionChecker') - ->shouldReceive('check') - ->andReturn(\Result\Result::ok('')) - ->getMock(); - } - - private function fakeInspectionCheckerWithResults($result_function) - { - return \Mockery::mock('\\Dxw\\Whippet\\Services\\InspectionChecker') - ->shouldReceive('check') - ->andReturnUsing($result_function) - ->getMock(); - } -} diff --git a/tests/dependencies/updater_test.php b/tests/dependencies/updater_test.php deleted file mode 100644 index 0278eb0e..00000000 --- a/tests/dependencies/updater_test.php +++ /dev/null @@ -1,1158 +0,0 @@ -getMockBuilder('\\Dxw\\Whippet\\Git\\Gitignore') - ->disableOriginalConstructor() - ->getMock(); - - $getIgnores = $gitignore->method('get_ignores'); - if ($warnOnGet) { - $getIgnores->will($this->returnCallback(function () { - trigger_error('$warOnGet set but not prevented', E_USER_WARNING); - })); - } else { - $getIgnores->willReturn($get); - } - - $gitignore->expects($this->exactly($saveIgnores ? 1 : 0)) - ->method('save_ignores') - ->with($save); - - return $gitignore; - } - - private function getWhippetLockWritable(array $addDependency, /* string */ $hash, /* string */ $path, array $getDependencies, /* boolean */ $setHash = true) - { - $whippetLock = $this->getMockBuilder('\\Dxw\\Whippet\\Files\\WhippetLock') - ->disableOriginalConstructor() - ->getMock(); - - call_user_func_array( - [ - $whippetLock->expects($this->exactly(count($addDependency))) - ->method('addDependency'), - 'withConsecutive', - ], - $addDependency - ); - - $whippetLock->expects($this->exactly($setHash === true ? 1 : 0)) - ->method('setHash') - ->with($hash); - - $whippetLock->expects($this->exactly($path === null ? 0 : 1)) - ->method('saveToPath') - ->with($path); - - if ($getDependencies === []) { - $getDependencies = [ - ['themes', []], - ['plugins', []], - ]; - } - - $whippetLock->method('getDependencies') - ->will($this->returnValueMap($getDependencies)); - - return $whippetLock; - } - - public function testUpdateAll() - { - $dir = $this->getDir(); - - $whippetJson = $this->getWhippetJson([ - 'src' => [ - 'themes' => 'git@github.com:dxw-wordpress-themes/', - 'plugins' => 'git@github.com:dxw-wordpress-plugins/', - ], - 'themes' => [ - [ - 'name' => 'my-theme', - 'ref' => 'v1.4', - ], - ], - 'plugins' => [ - [ - 'name' => 'my-plugin', - 'ref' => 'v1.6', - ], - ], - ]); - $this->addFactoryCallStatic('\\Dxw\\Whippet\\Files\\WhippetJson', 'fromFile', $dir.'/whippet.json', \Result\Result::ok($whippetJson)); - - file_put_contents($dir.'/whippet.json', 'foobar'); - - $gitignore = $this->getGitignore([], [ - "/wp-content/themes/my-theme\n", - "/wp-content/plugins/my-plugin\n", - ], true, false); - $this->addFactoryNewInstance('\\Dxw\\Whippet\\Git\\Gitignore', $dir, $gitignore); - - $whippetLock = $this->getWhippetLockWritable([ - ['themes', 'my-theme', 'git@github.com:dxw-wordpress-themes/my-theme', '27ba906'], - ['plugins', 'my-plugin', 'git@github.com:dxw-wordpress-plugins/my-plugin', 'd961c3d'], - ], sha1('foobar'), $dir.'/whippet.lock', []); - $this->addFactoryCallStatic('\\Dxw\\Whippet\\Files\\WhippetLock', 'fromFile', $dir.'/whippet.lock', \Result\Result::ok($whippetLock)); - - $this->addFactoryCallStatic('\\Dxw\\Whippet\\Git\\Git', 'ls_remote', 'git@github.com:dxw-wordpress-themes/my-theme', 'v1.4', \Result\Result::ok('27ba906')); - $this->addFactoryCallStatic('\\Dxw\\Whippet\\Git\\Git', 'ls_remote', 'git@github.com:dxw-wordpress-plugins/my-plugin', 'v1.6', \Result\Result::ok('d961c3d')); - - $dependencies = new \Dxw\Whippet\Dependencies\Updater( - $this->getFactory(), - $this->getProjectDirectory($dir) - ); - - ob_start(); - $result = $dependencies->updateAll(); - $output = ob_get_clean(); - - $this->assertFalse($result->isErr()); - $this->assertEquals("[Updating themes/my-theme]\n[Updating plugins/my-plugin]\n", $output); - } - - public function testUpdateAllWithExistingGitignore() - { - $dir = $this->getDir(); - touch($dir.'/.gitignore'); - - $whippetJson = $this->getWhippetJson([ - 'src' => [ - 'themes' => 'git@github.com:dxw-wordpress-themes/', - ], - 'themes' => [ - [ - 'name' => 'my-theme', - 'ref' => 'v1.4', - ], - ], - ]); - $this->addFactoryCallStatic('\\Dxw\\Whippet\\Files\\WhippetJson', 'fromFile', $dir.'/whippet.json', \Result\Result::ok($whippetJson)); - - file_put_contents($dir.'/whippet.json', 'foobar'); - - $gitignore = $this->getGitignore([ - "/wp-content/languages\n", - "/node_modules\n", - "/vendor\n", - ], [ - "/wp-content/languages\n", - "/node_modules\n", - "/vendor\n", - "/wp-content/themes/my-theme\n", - ], true, false); - $this->addFactoryNewInstance('\\Dxw\\Whippet\\Git\\Gitignore', $dir, $gitignore); - - $whippetLock = $this->getWhippetLockWritable([ - ['themes', 'my-theme', 'git@github.com:dxw-wordpress-themes/my-theme', '27ba906'], - ], sha1('foobar'), $dir.'/whippet.lock', []); - $this->addFactoryCallStatic('\\Dxw\\Whippet\\Files\\WhippetLock', 'fromFile', $dir.'/whippet.lock', \Result\Result::ok($whippetLock)); - - $this->addFactoryCallStatic('\\Dxw\\Whippet\\Git\\Git', 'ls_remote', 'git@github.com:dxw-wordpress-themes/my-theme', 'v1.4', \Result\Result::ok('27ba906')); - - $dependencies = new \Dxw\Whippet\Dependencies\Updater( - $this->getFactory(), - $this->getProjectDirectory($dir) - ); - - ob_start(); - $result = $dependencies->updateAll(); - $output = ob_get_clean(); - - $this->assertFalse($result->isErr()); - $this->assertEquals("[Updating themes/my-theme]\n", $output); - } - - public function testUpdateAllWithExistingGitignoreNoDuplication() - { - $dir = $this->getDir(); - touch($dir.'/.gitignore'); - - $whippetJson = $this->getWhippetJson([ - 'src' => [ - 'themes' => 'git@github.com:dxw-wordpress-themes/', - ], - 'themes' => [ - [ - 'name' => 'my-theme', - 'ref' => 'v1.4', - ], - ], - ]); - $this->addFactoryCallStatic('\\Dxw\\Whippet\\Files\\WhippetJson', 'fromFile', $dir.'/whippet.json', \Result\Result::ok($whippetJson)); - - file_put_contents($dir.'/whippet.json', 'foobar'); - - $gitignore = $this->getGitignore([ - "/wp-content/languages\n", - "/node_modules\n", - "/vendor\n", - "/wp-content/themes/my-theme\n", - ], [ - "/wp-content/languages\n", - "/node_modules\n", - "/vendor\n", - "/wp-content/themes/my-theme\n", - ], true, false); - $this->addFactoryNewInstance('\\Dxw\\Whippet\\Git\\Gitignore', $dir, $gitignore); - - $whippetLock = $this->getWhippetLockWritable([ - ['themes', 'my-theme', 'git@github.com:dxw-wordpress-themes/my-theme', '27ba906'], - ], sha1('foobar'), $dir.'/whippet.lock', []); - $this->addFactoryCallStatic('\\Dxw\\Whippet\\Files\\WhippetLock', 'fromFile', $dir.'/whippet.lock', \Result\Result::ok($whippetLock)); - - $this->addFactoryCallStatic('\\Dxw\\Whippet\\Git\\Git', 'ls_remote', 'git@github.com:dxw-wordpress-themes/my-theme', 'v1.4', \Result\Result::ok('27ba906')); - - $dependencies = new \Dxw\Whippet\Dependencies\Updater( - $this->getFactory(), - $this->getProjectDirectory($dir) - ); - - ob_start(); - $result = $dependencies->updateAll(); - $output = ob_get_clean(); - - $this->assertFalse($result->isErr()); - $this->assertEquals("[Updating themes/my-theme]\n", $output); - } - - public function testUpdateAllFailedGitCommand() - { - $dir = $this->getDir(); - - $whippetJson = $this->getWhippetJson([ - 'src' => [ - 'themes' => 'git@github.com:dxw-wordpress-themes/', - ], - 'themes' => [ - [ - 'name' => 'my-theme', - 'ref' => 'v1.4', - ], - ], - ]); - $this->addFactoryCallStatic('\\Dxw\\Whippet\\Files\\WhippetJson', 'fromFile', $dir.'/whippet.json', \Result\Result::ok($whippetJson)); - - file_put_contents($dir.'/whippet.json', 'foobar'); - - $gitignore = $this->getGitignore([], [ - "/wp-content/themes/my-theme\n", - ], false, false); - $this->addFactoryNewInstance('\\Dxw\\Whippet\\Git\\Gitignore', $dir, $gitignore); - - $whippetLock = $this->getWhippetLockWritable([], sha1('foobar'), null, []); - $this->addFactoryCallStatic('\\Dxw\\Whippet\\Files\\WhippetLock', 'fromFile', $dir.'/whippet.lock', \Result\Result::ok($whippetLock)); - - $this->addFactoryCallStatic('\\Dxw\\Whippet\\Git\\Git', 'ls_remote', 'git@github.com:dxw-wordpress-themes/my-theme', 'v1.4', \Result\Result::err('oh no')); - - $dependencies = new \Dxw\Whippet\Dependencies\Updater( - $this->getFactory(), - $this->getProjectDirectory($dir) - ); - - ob_start(); - $result = $dependencies->updateAll(); - $output = ob_get_clean(); - - $this->assertTrue($result->isErr()); - $this->assertEquals('git command failed: oh no', $result->getErr()); - $this->assertEquals("[Updating themes/my-theme]\n", $output); - } - - public function testUpdateAllWithExplicitSrc() - { - $dir = $this->getDir(); - - $whippetJson = $this->getWhippetJson([ - 'src' => [ - 'themes' => 'git@github.com:dxw-wordpress-themes/', - ], - 'themes' => [ - [ - 'name' => 'my-theme', - 'ref' => 'v1.4', - 'src' => 'foobar', - ], - ], - ]); - $this->addFactoryCallStatic('\\Dxw\\Whippet\\Files\\WhippetJson', 'fromFile', $dir.'/whippet.json', \Result\Result::ok($whippetJson)); - - file_put_contents($dir.'/whippet.json', 'foobar'); - - $gitignore = $this->getGitignore([], [ - "/wp-content/themes/my-theme\n", - ], true, false); - $this->addFactoryNewInstance('\\Dxw\\Whippet\\Git\\Gitignore', $dir, $gitignore); - - $whippetLock = $this->getWhippetLockWritable([ - ['themes', 'my-theme', 'foobar', '27ba906'], - ], sha1('foobar'), $dir.'/whippet.lock', []); - $this->addFactoryCallStatic('\\Dxw\\Whippet\\Files\\WhippetLock', 'fromFile', $dir.'/whippet.lock', \Result\Result::ok($whippetLock)); - - $this->addFactoryCallStatic('\\Dxw\\Whippet\\Git\\Git', 'ls_remote', 'foobar', 'v1.4', \Result\Result::ok('27ba906')); - - $dependencies = new \Dxw\Whippet\Dependencies\Updater( - $this->getFactory(), - $this->getProjectDirectory($dir) - ); - - ob_start(); - $result = $dependencies->updateAll(); - $output = ob_get_clean(); - - $this->assertFalse($result->isErr()); - $this->assertEquals("[Updating themes/my-theme]\n", $output); - } - - public function testUpdateAllWithoutRef() - { - $dir = $this->getDir(); - - $whippetJson = $this->getWhippetJson([ - 'src' => [ - 'themes' => 'git@github.com:dxw-wordpress-themes/', - ], - 'themes' => [ - [ - 'name' => 'my-theme', - ], - ], - ]); - $this->addFactoryCallStatic('\\Dxw\\Whippet\\Files\\WhippetJson', 'fromFile', $dir.'/whippet.json', \Result\Result::ok($whippetJson)); - - file_put_contents($dir.'/whippet.json', 'foobar'); - - $gitignore = $this->getGitignore([], [ - "/wp-content/themes/my-theme\n", - ], true, false); - $this->addFactoryNewInstance('\\Dxw\\Whippet\\Git\\Gitignore', $dir, $gitignore); - - $whippetLock = $this->getWhippetLockWritable([ - ['themes', 'my-theme', 'git@github.com:dxw-wordpress-themes/my-theme', '27ba906'], - ], sha1('foobar'), $dir.'/whippet.lock', []); - $this->addFactoryCallStatic('\\Dxw\\Whippet\\Files\\WhippetLock', 'fromFile', $dir.'/whippet.lock', \Result\Result::ok($whippetLock)); - - $this->addFactoryCallStatic('\\Dxw\\Whippet\\Git\\Git', 'ls_remote', 'git@github.com:dxw-wordpress-themes/my-theme', 'main', \Result\Result::ok('27ba906')); - - $dependencies = new \Dxw\Whippet\Dependencies\Updater( - $this->getFactory(), - $this->getProjectDirectory($dir) - ); - - ob_start(); - $result = $dependencies->updateAll(); - $output = ob_get_clean(); - - $this->assertFalse($result->isErr()); - $this->assertEquals("[Updating themes/my-theme]\n", $output); - } - - public function testUpdateAllWithoutRefUsingMaster() - { - $dir = $this->getDir(); - - $whippetJson = $this->getWhippetJson([ - 'src' => [ - 'themes' => 'git@github.com:dxw-wordpress-themes/', - ], - 'themes' => [ - [ - 'name' => 'my-theme', - ], - ], - ]); - $this->addFactoryCallStatic('\\Dxw\\Whippet\\Files\\WhippetJson', 'fromFile', $dir.'/whippet.json', \Result\Result::ok($whippetJson)); - - file_put_contents($dir.'/whippet.json', 'foobar'); - - $gitignore = $this->getGitignore([], [ - "/wp-content/themes/my-theme\n", - ], true, false); - $this->addFactoryNewInstance('\\Dxw\\Whippet\\Git\\Gitignore', $dir, $gitignore); - - $whippetLock = $this->getWhippetLockWritable([ - ['themes', 'my-theme', 'git@github.com:dxw-wordpress-themes/my-theme', '27ba906'], - ], sha1('foobar'), $dir.'/whippet.lock', []); - $this->addFactoryCallStatic('\\Dxw\\Whippet\\Files\\WhippetLock', 'fromFile', $dir.'/whippet.lock', \Result\Result::ok($whippetLock)); - - $this->addFactoryCallStatic('\\Dxw\\Whippet\\Git\\Git', 'ls_remote', 'git@github.com:dxw-wordpress-themes/my-theme', 'main', \Result\Result::err('no such branch')); - $this->addFactoryCallStatic('\\Dxw\\Whippet\\Git\\Git', 'ls_remote', 'git@github.com:dxw-wordpress-themes/my-theme', 'master', \Result\Result::ok('27ba906')); - - $dependencies = new \Dxw\Whippet\Dependencies\Updater( - $this->getFactory(), - $this->getProjectDirectory($dir) - ); - - ob_start(); - $result = $dependencies->updateAll(); - $output = ob_get_clean(); - - $this->assertFalse($result->isErr()); - $this->assertEquals("[Updating themes/my-theme]\n", $output); - } - - public function testUpdateAllBlankJsonfile() - { - $dir = $this->getDir(); - - $whippetJson = $this->getWhippetJson([]); - $this->addFactoryCallStatic('\\Dxw\\Whippet\\Files\\WhippetJson', 'fromFile', $dir.'/whippet.json', \Result\Result::ok($whippetJson)); - - file_put_contents($dir.'/whippet.json', 'foobar'); - - $gitignore = $this->getGitignore([], [], true, false); - $this->addFactoryNewInstance('\\Dxw\\Whippet\\Git\\Gitignore', $dir, $gitignore); - - $whippetLock = $this->getWhippetLockWritable([], sha1('foobar'), $dir.'/whippet.lock', []); - $this->addFactoryCallStatic('\\Dxw\\Whippet\\Files\\WhippetLock', 'fromFile', $dir.'/whippet.lock', \Result\Result::ok($whippetLock)); - - $dependencies = new \Dxw\Whippet\Dependencies\Updater( - $this->getFactory(), - $this->getProjectDirectory($dir) - ); - - ob_start(); - $result = $dependencies->updateAll(); - $output = ob_get_clean(); - - $this->assertFalse($result->isErr()); - $this->assertEquals("whippet.json contains no dependencies\n", $output); - } - - public function testUpdateAllNoGitignore() - { - $dir = $this->getDir(); - - $whippetJson = $this->getWhippetJson([ - 'src' => [ - 'themes' => 'git@github.com:dxw-wordpress-themes/', - 'plugins' => 'git@github.com:dxw-wordpress-plugins/', - ], - 'themes' => [ - [ - 'name' => 'my-theme', - 'ref' => 'v1.4', - ], - ], - 'plugins' => [ - [ - 'name' => 'my-plugin', - 'ref' => 'v1.6', - ], - ], - ]); - $this->addFactoryCallStatic('\\Dxw\\Whippet\\Files\\WhippetJson', 'fromFile', $dir.'/whippet.json', \Result\Result::ok($whippetJson)); - - file_put_contents($dir.'/whippet.json', 'foobar'); - - $gitignore = $this->getGitignore([], [ - "/wp-content/themes/my-theme\n", - "/wp-content/plugins/my-plugin\n", - ], true, true); - $this->addFactoryNewInstance('\\Dxw\\Whippet\\Git\\Gitignore', $dir, $gitignore); - - $whippetLock = $this->getWhippetLockWritable([ - ['themes', 'my-theme', 'git@github.com:dxw-wordpress-themes/my-theme', '27ba906'], - ['plugins', 'my-plugin', 'git@github.com:dxw-wordpress-plugins/my-plugin', 'd961c3d'], - ], sha1('foobar'), $dir.'/whippet.lock', []); - $this->addFactoryCallStatic('\\Dxw\\Whippet\\Files\\WhippetLock', 'fromFile', $dir.'/whippet.lock', \Result\Result::ok($whippetLock)); - - $this->addFactoryCallStatic('\\Dxw\\Whippet\\Git\\Git', 'ls_remote', 'git@github.com:dxw-wordpress-themes/my-theme', 'v1.4', \Result\Result::ok('27ba906')); - $this->addFactoryCallStatic('\\Dxw\\Whippet\\Git\\Git', 'ls_remote', 'git@github.com:dxw-wordpress-plugins/my-plugin', 'v1.6', \Result\Result::ok('d961c3d')); - - $dependencies = new \Dxw\Whippet\Dependencies\Updater( - $this->getFactory(), - $this->getProjectDirectory($dir) - ); - - ob_start(); - $result = $dependencies->updateAll(); - $output = ob_get_clean(); - - $this->assertFalse($result->isErr()); - $this->assertEquals("[Updating themes/my-theme]\n[Updating plugins/my-plugin]\n", $output); - } - - public function testUpdateAllRemoveFromGitignore() - { - $dir = $this->getDir(); - touch($dir.'/.gitignore'); - - $whippetJson = $this->getWhippetJson([ - 'src' => [ - 'themes' => 'git@github.com:dxw-wordpress-themes/', - ], - 'themes' => [ - [ - 'name' => 'my-theme', - 'ref' => 'v1.4', - ], - ], - ]); - $this->addFactoryCallStatic('\\Dxw\\Whippet\\Files\\WhippetJson', 'fromFile', $dir.'/whippet.json', \Result\Result::ok($whippetJson)); - - file_put_contents($dir.'/whippet.json', 'foobar'); - - $gitignore = $this->getGitignore([ - "/wp-content/themes/my-theme\n", - "/wp-content/plugins/unmanaged-plugin\n", - "/wp-content/plugins/removed-plugin\n", - ], [ - "/wp-content/themes/my-theme\n", - "/wp-content/plugins/unmanaged-plugin\n", - ], true, false); - $this->addFactoryNewInstance('\\Dxw\\Whippet\\Git\\Gitignore', $dir, $gitignore); - - $whippetLock = $this->getWhippetLockWritable([ - ['themes', 'my-theme', 'git@github.com:dxw-wordpress-themes/my-theme', '27ba906'], - ], sha1('foobar'), $dir.'/whippet.lock', [ - ['themes', []], - ['plugins', [ - ['name' => 'removed-plugin'], - ]], - ]); - $this->addFactoryCallStatic('\\Dxw\\Whippet\\Files\\WhippetLock', 'fromFile', $dir.'/whippet.lock', \Result\Result::ok($whippetLock)); - - $this->addFactoryCallStatic('\\Dxw\\Whippet\\Git\\Git', 'ls_remote', 'git@github.com:dxw-wordpress-themes/my-theme', 'v1.4', \Result\Result::ok('27ba906')); - $this->addFactoryCallStatic('\\Dxw\\Whippet\\Git\\Git', 'ls_remote', 'git@github.com:dxw-wordpress-plugins/my-plugin', 'v1.6', \Result\Result::ok('d961c3d')); - - $dependencies = new \Dxw\Whippet\Dependencies\Updater( - $this->getFactory(), - $this->getProjectDirectory($dir) - ); - - ob_start(); - $result = $dependencies->updateAll(); - $output = ob_get_clean(); - - $this->assertFalse($result->isErr()); - $this->assertEquals("[Updating themes/my-theme]\n", $output); - } - - public function testUpdateAllBubbleErrors() - { - $dir = $this->getDir(); - - $this->addFactoryCallStatic('\\Dxw\\Whippet\\Files\\WhippetJson', 'fromFile', $dir.'/whippet.json', \Result\Result::err('a WhippetJson error')); - - $dependencies = new \Dxw\Whippet\Dependencies\Updater( - $this->getFactory(), - $this->getProjectDirectory($dir) - ); - - ob_start(); - $result = $dependencies->updateAll(); - $output = ob_get_clean(); - - $this->assertTrue($result->isErr()); - $this->assertEquals('whippet.json: a WhippetJson error', $result->getErr()); - $this->assertEquals('', $output); - } - - public function testUpdateAllNoExistingWhippetLock() - { - $dir = $this->getDir(); - - $whippetJson = $this->getWhippetJson([ - 'src' => [ - 'themes' => 'git@github.com:dxw-wordpress-themes/', - 'plugins' => 'git@github.com:dxw-wordpress-plugins/', - ], - 'themes' => [ - [ - 'name' => 'my-theme', - 'ref' => 'v1.4', - ], - ], - 'plugins' => [ - [ - 'name' => 'my-plugin', - 'ref' => 'v1.6', - ], - ], - ]); - $this->addFactoryCallStatic('\\Dxw\\Whippet\\Files\\WhippetJson', 'fromFile', $dir.'/whippet.json', \Result\Result::ok($whippetJson)); - - file_put_contents($dir.'/whippet.json', 'foobar'); - - $gitignore = $this->getGitignore([], [ - "/wp-content/themes/my-theme\n", - "/wp-content/plugins/my-plugin\n", - ], true, false); - $this->addFactoryNewInstance('\\Dxw\\Whippet\\Git\\Gitignore', $dir, $gitignore); - - $whippetLock = $this->getWhippetLockWritable([ - ['themes', 'my-theme', 'git@github.com:dxw-wordpress-themes/my-theme', '27ba906'], - ['plugins', 'my-plugin', 'git@github.com:dxw-wordpress-plugins/my-plugin', 'd961c3d'], - ], sha1('foobar'), $dir.'/whippet.lock', []); - $this->addFactoryNewInstance('\\Dxw\\Whippet\\Files\\WhippetLock', [], $whippetLock); - - $this->addFactoryCallStatic('\\Dxw\\Whippet\\Git\\Git', 'ls_remote', 'git@github.com:dxw-wordpress-themes/my-theme', 'v1.4', \Result\Result::ok('27ba906')); - $this->addFactoryCallStatic('\\Dxw\\Whippet\\Git\\Git', 'ls_remote', 'git@github.com:dxw-wordpress-plugins/my-plugin', 'v1.6', \Result\Result::ok('d961c3d')); - $this->addFactoryCallStatic('\\Dxw\\Whippet\\Files\\WhippetLock', 'fromFile', $dir.'/whippet.lock', \Result\Result::err('file not found')); - - $dependencies = new \Dxw\Whippet\Dependencies\Updater( - $this->getFactory(), - $this->getProjectDirectory($dir) - ); - - ob_start(); - $result = $dependencies->updateAll(); - $output = ob_get_clean(); - - $this->assertFalse($result->isErr()); - $this->assertEquals("[Updating themes/my-theme]\n[Updating plugins/my-plugin]\n", $output); - } - - public function testUpdateAllWithBrokenJson() - { - $dir = $this->getDir(); - - $whippetJson = $this->getWhippetJson([ - 'src' => [ - 'plugins' => 'git@github.com:dxw-wordpress-plugins/', - ], - 'themes' => [ - [ - 'name' => 'my-theme', - 'ref' => 'v1.4', - ], - ], - 'plugins' => [ - [ - 'name' => 'my-plugin', - 'ref' => 'v1.6', - ], - ], - ]); - $this->addFactoryCallStatic('\\Dxw\\Whippet\\Files\\WhippetJson', 'fromFile', $dir.'/whippet.json', \Result\Result::ok($whippetJson)); - - file_put_contents($dir.'/whippet.json', 'foobar'); - - $gitignore = $this->getGitignore([], [ - "/wp-content/themes/my-theme\n", - "/wp-content/plugins/my-plugin\n", - ], false, false); - $this->addFactoryNewInstance('\\Dxw\\Whippet\\Git\\Gitignore', $dir, $gitignore); - - $whippetLock = $this->getWhippetLockWritable([], sha1('foobar'), null, []); - $this->addFactoryCallStatic('\\Dxw\\Whippet\\Files\\WhippetLock', 'fromFile', $dir.'/whippet.lock', \Result\Result::ok($whippetLock)); - - $this->addFactoryCallStatic('\\Dxw\\Whippet\\Git\\Git', 'ls_remote', 'git@github.com:dxw-wordpress-themes/my-theme', 'v1.4', \Result\Result::ok('27ba906')); - $this->addFactoryCallStatic('\\Dxw\\Whippet\\Git\\Git', 'ls_remote', 'git@github.com:dxw-wordpress-plugins/my-plugin', 'v1.6', \Result\Result::ok('d961c3d')); - - $dependencies = new \Dxw\Whippet\Dependencies\Updater( - $this->getFactory(), - $this->getProjectDirectory($dir) - ); - - ob_start(); - $result = $dependencies->updateAll(); - $output = ob_get_clean(); - - $this->assertTrue($result->isErr()); - $this->assertEquals('missing sources', $result->getErr()); - $this->assertEquals("[Updating themes/my-theme]\n", $output); - } - - public function testUpdateSingleWithNoLock() - { - $dir = $this->getDir(); - - $this->addFactoryCallStatic('\\Dxw\\Whippet\\Files\\WhippetLock', 'fromFile', $dir.'/whippet.lock', \Result\Result::err('file not found')); - - $dependencies = new \Dxw\Whippet\Dependencies\Updater( - $this->getFactory(), - $this->getProjectDirectory($dir) - ); - - ob_start(); - $result = $dependencies->updateSingle('twitget'); - $output = ob_get_clean(); - - $this->assertTrue($result->isErr()); - $this->assertEquals("No whippet.lock file exists, you need to run `whippet deps update` to generate one before you can update a specific dependency. \n", $output); - $this->assertEquals('whippet.lock: file not found', $result->getErr()); - } - - public function testUpdateSingleIncorrectFormat() - { - $dir = $this->getDir(); - - file_put_contents($dir.'/whippet.json', 'foobar'); - - $whippetLock = []; - $this->addFactoryCallStatic('\\Dxw\\Whippet\\Files\\WhippetLock', 'fromFile', $dir.'/whippet.lock', \Result\Result::ok($whippetLock)); - - $dependencies = new \Dxw\Whippet\Dependencies\Updater( - $this->getFactory(), - $this->getProjectDirectory($dir) - ); - - ob_start(); - $result = $dependencies->updateSingle('twitget'); - $output = ob_get_clean(); - - $this->assertTrue($result->isErr()); - $this->assertEquals("Dependency should be in format [type]/[name]. \n", $output); - $this->assertEquals('Incorrect dependency format', $result->getErr()); - } - - public function testUpdateSingleNoMatch() - { - $dir = $this->getDir(); - file_put_contents($dir.'/whippet.json', 'foobar'); - $whippetJson = $this->getWhippetJson([ - 'src' => [ - 'plugins' => 'git@github.com:dxw-wordpress-plugins/', - ], - 'themes' => [ - [ - 'name' => 'my-theme', - 'ref' => 'v1.4', - ], - ], - 'plugins' => [ - [ - 'name' => 'my-plugin', - 'ref' => 'v1.6', - ], - ], - ]); - $this->addFactoryCallStatic('\\Dxw\\Whippet\\Files\\WhippetJson', 'fromFile', $dir.'/whippet.json', \Result\Result::ok($whippetJson)); - - - $whippetLock = $this->getWhippetLockWritable([], sha1('foobar'), null, [], false); - $this->addFactoryCallStatic('\\Dxw\\Whippet\\Files\\WhippetLock', 'fromFile', $dir.'/whippet.lock', \Result\Result::ok($whippetLock)); - - $dependencies = new \Dxw\Whippet\Dependencies\Updater( - $this->getFactory(), - $this->getProjectDirectory($dir) - ); - - ob_start(); - $result = $dependencies->updateSingle('plugins/twitget'); - $output = ob_get_clean(); - - $this->assertTrue($result->isErr()); - $this->assertEquals('No matching dependency in whippet.json', $result->getErr()); - } - - public function testUpdateSingleBrokenJson() - { - $dir = $this->getDir(); - - $whippetJson = $this->getWhippetJson([ - 'src' => [ - 'plugins' => 'git@github.com:dxw-wordpress-plugins/', - ], - 'themes' => [ - [ - 'name' => 'my-theme', - 'ref' => 'v1.4', - ], - ], - 'plugins' => [ - [ - 'name' => 'my-plugin', - 'ref' => 'v1.6', - ], - ], - ]); - $this->addFactoryCallStatic('\\Dxw\\Whippet\\Files\\WhippetJson', 'fromFile', $dir.'/whippet.json', \Result\Result::ok($whippetJson)); - - file_put_contents($dir.'/whippet.json', 'foobar'); - - $gitignore = $this->getGitignore([], [ - "/wp-content/themes/my-theme\n", - "/wp-content/plugins/my-plugin\n", - ], false, false); - $this->addFactoryNewInstance('\\Dxw\\Whippet\\Git\\Gitignore', $dir, $gitignore); - - $whippetLock = $this->getWhippetLockWritable([], sha1('foobar'), null, []); - $this->addFactoryCallStatic('\\Dxw\\Whippet\\Files\\WhippetLock', 'fromFile', $dir.'/whippet.lock', \Result\Result::ok($whippetLock)); - - $this->addFactoryCallStatic('\\Dxw\\Whippet\\Git\\Git', 'ls_remote', 'git@github.com:dxw-wordpress-themes/my-theme', 'v1.4', \Result\Result::ok('27ba906')); - $this->addFactoryCallStatic('\\Dxw\\Whippet\\Git\\Git', 'ls_remote', 'git@github.com:dxw-wordpress-plugins/my-plugin', 'v1.6', \Result\Result::ok('d961c3d')); - - $dependencies = new \Dxw\Whippet\Dependencies\Updater( - $this->getFactory(), - $this->getProjectDirectory($dir) - ); - - ob_start(); - $result = $dependencies->updateSingle('themes/my-theme'); - $output = ob_get_clean(); - - $this->assertTrue($result->isErr()); - $this->assertEquals('missing sources', $result->getErr()); - $this->assertEquals("[Updating themes/my-theme]\n", $output); - } - - public function testUpdateSingleWithExistingGitignore() - { - $dir = $this->getDir(); - touch($dir.'/.gitignore'); - - $whippetJson = $this->getWhippetJson([ - 'src' => [ - 'themes' => 'git@github.com:dxw-wordpress-themes/', - ], - 'themes' => [ - [ - 'name' => 'my-theme', - 'ref' => 'v1.4', - ], - ], - ]); - $this->addFactoryCallStatic('\\Dxw\\Whippet\\Files\\WhippetJson', 'fromFile', $dir.'/whippet.json', \Result\Result::ok($whippetJson)); - - file_put_contents($dir.'/whippet.json', 'foobar'); - - $gitignore = $this->getGitignore([ - "/wp-content/languages\n", - "/node_modules\n", - "/vendor\n", - ], [ - "/wp-content/languages\n", - "/node_modules\n", - "/vendor\n", - "/wp-content/themes/my-theme\n", - ], true, false); - $this->addFactoryNewInstance('\\Dxw\\Whippet\\Git\\Gitignore', $dir, $gitignore); - - $whippetLock = $this->getWhippetLockWritable([ - ['themes', 'my-theme', 'git@github.com:dxw-wordpress-themes/my-theme', '27ba906'], - ], sha1('foobar'), $dir.'/whippet.lock', []); - $this->addFactoryCallStatic('\\Dxw\\Whippet\\Files\\WhippetLock', 'fromFile', $dir.'/whippet.lock', \Result\Result::ok($whippetLock)); - - $this->addFactoryCallStatic('\\Dxw\\Whippet\\Git\\Git', 'ls_remote', 'git@github.com:dxw-wordpress-themes/my-theme', 'v1.4', \Result\Result::ok('27ba906')); - - $dependencies = new \Dxw\Whippet\Dependencies\Updater( - $this->getFactory(), - $this->getProjectDirectory($dir) - ); - - ob_start(); - $result = $dependencies->updateSingle('themes/my-theme'); - $output = ob_get_clean(); - - $this->assertFalse($result->isErr()); - $this->assertEquals("[Updating themes/my-theme]\n", $output); - } - - public function testUpdateSingleWithExistingGitignoreNoDuplication() - { - $dir = $this->getDir(); - touch($dir.'/.gitignore'); - - $whippetJson = $this->getWhippetJson([ - 'src' => [ - 'themes' => 'git@github.com:dxw-wordpress-themes/', - ], - 'themes' => [ - [ - 'name' => 'my-theme', - 'ref' => 'v1.4', - ], - ], - ]); - $this->addFactoryCallStatic('\\Dxw\\Whippet\\Files\\WhippetJson', 'fromFile', $dir.'/whippet.json', \Result\Result::ok($whippetJson)); - - file_put_contents($dir.'/whippet.json', 'foobar'); - - $gitignore = $this->getGitignore([ - "/wp-content/languages\n", - "/node_modules\n", - "/vendor\n", - "/wp-content/themes/my-theme\n", - ], [ - "/wp-content/languages\n", - "/node_modules\n", - "/vendor\n", - "/wp-content/themes/my-theme\n", - ], true, false); - $this->addFactoryNewInstance('\\Dxw\\Whippet\\Git\\Gitignore', $dir, $gitignore); - - $whippetLock = $this->getWhippetLockWritable([ - ['themes', 'my-theme', 'git@github.com:dxw-wordpress-themes/my-theme', '27ba906'], - ], sha1('foobar'), $dir.'/whippet.lock', []); - $this->addFactoryCallStatic('\\Dxw\\Whippet\\Files\\WhippetLock', 'fromFile', $dir.'/whippet.lock', \Result\Result::ok($whippetLock)); - - $this->addFactoryCallStatic('\\Dxw\\Whippet\\Git\\Git', 'ls_remote', 'git@github.com:dxw-wordpress-themes/my-theme', 'v1.4', \Result\Result::ok('27ba906')); - - $dependencies = new \Dxw\Whippet\Dependencies\Updater( - $this->getFactory(), - $this->getProjectDirectory($dir) - ); - - ob_start(); - $result = $dependencies->updateSingle('themes/my-theme'); - $output = ob_get_clean(); - - $this->assertFalse($result->isErr()); - $this->assertEquals("[Updating themes/my-theme]\n", $output); - } - - public function testUpdateSingleFailedGitCommand() - { - $dir = $this->getDir(); - - $whippetJson = $this->getWhippetJson([ - 'src' => [ - 'themes' => 'git@github.com:dxw-wordpress-themes/', - ], - 'themes' => [ - [ - 'name' => 'my-theme', - 'ref' => 'v1.4', - ], - ], - 'plugins' => [ - [ - 'name' => 'twitget', - ], - ], - ]); - $this->addFactoryCallStatic('\\Dxw\\Whippet\\Files\\WhippetJson', 'fromFile', $dir.'/whippet.json', \Result\Result::ok($whippetJson)); - - file_put_contents($dir.'/whippet.json', 'foobar'); - - $gitignore = $this->getGitignore([], [ - "/wp-content/themes/my-theme\n", - ], false, false); - $this->addFactoryNewInstance('\\Dxw\\Whippet\\Git\\Gitignore', $dir, $gitignore); - - $whippetLock = $this->getWhippetLockWritable([], sha1('foobar'), null, []); - $this->addFactoryCallStatic('\\Dxw\\Whippet\\Files\\WhippetLock', 'fromFile', $dir.'/whippet.lock', \Result\Result::ok($whippetLock)); - - $this->addFactoryCallStatic('\\Dxw\\Whippet\\Git\\Git', 'ls_remote', 'git@github.com:dxw-wordpress-themes/my-theme', 'v1.4', \Result\Result::err('oh no')); - - $dependencies = new \Dxw\Whippet\Dependencies\Updater( - $this->getFactory(), - $this->getProjectDirectory($dir) - ); - - ob_start(); - $result = $dependencies->updateSingle('themes/my-theme'); - $output = ob_get_clean(); - - $this->assertTrue($result->isErr()); - $this->assertEquals('git command failed: oh no', $result->getErr()); - $this->assertEquals("[Updating themes/my-theme]\n", $output); - } - - public function testUpdateSingleWithExplicitSrc() - { - $dir = $this->getDir(); - - $whippetJson = $this->getWhippetJson([ - 'src' => [ - 'themes' => 'git@github.com:dxw-wordpress-themes/', - 'plugins' => 'git@github.com:dxw-wordpress-plugins/', - ], - 'themes' => [ - [ - 'name' => 'my-theme', - 'ref' => 'v1.4', - 'src' => 'foobar', - ], - ], - 'plugins' => [ - [ - 'name' => 'twitget', - 'ref' => 'v1.4', - 'src' => 'foobar', - ], - ], - ]); - $this->addFactoryCallStatic('\\Dxw\\Whippet\\Files\\WhippetJson', 'fromFile', $dir.'/whippet.json', \Result\Result::ok($whippetJson)); - - file_put_contents($dir.'/whippet.json', 'foobar'); - - $gitignore = $this->getGitignore([], [ - "/wp-content/themes/my-theme\n", - "/wp-content/plugins/twitget\n" - ], true, false); - $this->addFactoryNewInstance('\\Dxw\\Whippet\\Git\\Gitignore', $dir, $gitignore); - - $whippetLock = $this->getWhippetLockWritable([ - ['themes', 'my-theme', 'foobar', '27ba906'], - ], sha1('foobar'), $dir.'/whippet.lock', []); - $this->addFactoryCallStatic('\\Dxw\\Whippet\\Files\\WhippetLock', 'fromFile', $dir.'/whippet.lock', \Result\Result::ok($whippetLock)); - - $this->addFactoryCallStatic('\\Dxw\\Whippet\\Git\\Git', 'ls_remote', 'foobar', 'v1.4', \Result\Result::ok('27ba906')); - - $dependencies = new \Dxw\Whippet\Dependencies\Updater( - $this->getFactory(), - $this->getProjectDirectory($dir) - ); - - ob_start(); - $result = $dependencies->updateSingle('themes/my-theme'); - $output = ob_get_clean(); - - $this->assertFalse($result->isErr()); - $this->assertEquals("[Updating themes/my-theme]\n", $output); - } - - public function testUpdateSingleWithoutRef() - { - $dir = $this->getDir(); - - $whippetJson = $this->getWhippetJson([ - 'src' => [ - 'themes' => 'git@github.com:dxw-wordpress-themes/', - ], - 'themes' => [ - [ - 'name' => 'my-theme', - ], - ], - 'plugins' => [ - [ - 'name' => 'my-plugin', - ], - ], - ]); - $this->addFactoryCallStatic('\\Dxw\\Whippet\\Files\\WhippetJson', 'fromFile', $dir.'/whippet.json', \Result\Result::ok($whippetJson)); - - file_put_contents($dir.'/whippet.json', 'foobar'); - - $gitignore = $this->getGitignore([], [ - "/wp-content/themes/my-theme\n", - "/wp-content/plugins/my-plugin\n", - ], true, false); - $this->addFactoryNewInstance('\\Dxw\\Whippet\\Git\\Gitignore', $dir, $gitignore); - - $whippetLock = $this->getWhippetLockWritable([ - ['themes', 'my-theme', 'git@github.com:dxw-wordpress-themes/my-theme', '27ba906'], - ], sha1('foobar'), $dir.'/whippet.lock', []); - $this->addFactoryCallStatic('\\Dxw\\Whippet\\Files\\WhippetLock', 'fromFile', $dir.'/whippet.lock', \Result\Result::ok($whippetLock)); - - $this->addFactoryCallStatic('\\Dxw\\Whippet\\Git\\Git', 'ls_remote', 'git@github.com:dxw-wordpress-themes/my-theme', 'main', \Result\Result::ok('27ba906')); - - $dependencies = new \Dxw\Whippet\Dependencies\Updater( - $this->getFactory(), - $this->getProjectDirectory($dir) - ); - - ob_start(); - $result = $dependencies->updateSingle('themes/my-theme'); - $output = ob_get_clean(); - - $this->assertFalse($result->isErr()); - $this->assertEquals("[Updating themes/my-theme]\n", $output); - } - - public function testUpdateSingleNoGitignore() - { - $dir = $this->getDir(); - - $whippetJson = $this->getWhippetJson([ - 'src' => [ - 'themes' => 'git@github.com:dxw-wordpress-themes/', - 'plugins' => 'git@github.com:dxw-wordpress-plugins/', - ], - 'themes' => [ - [ - 'name' => 'my-theme', - 'ref' => 'v1.4', - ], - ], - 'plugins' => [ - [ - 'name' => 'my-plugin', - 'ref' => 'v1.6', - ], - ], - ]); - $this->addFactoryCallStatic('\\Dxw\\Whippet\\Files\\WhippetJson', 'fromFile', $dir.'/whippet.json', \Result\Result::ok($whippetJson)); - - file_put_contents($dir.'/whippet.json', 'foobar'); - - $gitignore = $this->getGitignore([], [ - "/wp-content/themes/my-theme\n", - "/wp-content/plugins/my-plugin\n", - ], true, true); - $this->addFactoryNewInstance('\\Dxw\\Whippet\\Git\\Gitignore', $dir, $gitignore); - - $whippetLock = $this->getWhippetLockWritable([ - ['themes', 'my-theme', 'git@github.com:dxw-wordpress-themes/my-theme', '27ba906'], - ], sha1('foobar'), $dir.'/whippet.lock', []); - $this->addFactoryCallStatic('\\Dxw\\Whippet\\Files\\WhippetLock', 'fromFile', $dir.'/whippet.lock', \Result\Result::ok($whippetLock)); - - $this->addFactoryCallStatic('\\Dxw\\Whippet\\Git\\Git', 'ls_remote', 'git@github.com:dxw-wordpress-themes/my-theme', 'v1.4', \Result\Result::ok('27ba906')); - $this->addFactoryCallStatic('\\Dxw\\Whippet\\Git\\Git', 'ls_remote', 'git@github.com:dxw-wordpress-plugins/my-plugin', 'v1.6', \Result\Result::ok('d961c3d')); - - $dependencies = new \Dxw\Whippet\Dependencies\Updater( - $this->getFactory(), - $this->getProjectDirectory($dir) - ); - - ob_start(); - $result = $dependencies->updateSingle('themes/my-theme'); - $output = ob_get_clean(); - - $this->assertFalse($result->isErr()); - $this->assertEquals("[Updating themes/my-theme]\n", $output); - } - - - public function testUpdateSingle() - { - $dir = $this->getDir(); - file_put_contents($dir.'/whippet.json', 'foobar'); - - $whippetJson = $this->getWhippetJson([ - 'src' => [ - 'plugins' => 'git@github.com:dxw-wordpress-plugins/', - ], - 'themes' => [ - [ - 'name' => 'my-theme', - 'ref' => 'v1.4', - ], - ], - 'plugins' => [ - [ - 'name' => 'my-plugin', - 'ref' => 'v1.6', - ], - ], - ]); - $this->addFactoryCallStatic('\\Dxw\\Whippet\\Files\\WhippetJson', 'fromFile', $dir.'/whippet.json', \Result\Result::ok($whippetJson)); - - $whippetLock = $this->getWhippetLockWritable([ - ['plugins', 'my-plugin', 'git@github.com:dxw-wordpress-plugins/my-plugin', 'd961c3d'], - ], sha1('foobar'), $dir.'/whippet.lock', []); - - $this->addFactoryCallStatic('\\Dxw\\Whippet\\Files\\WhippetLock', 'fromFile', $dir.'/whippet.lock', \Result\Result::ok($whippetLock)); - - $this->addFactoryCallStatic('\\Dxw\\Whippet\\Git\\Git', 'ls_remote', 'git@github.com:dxw-wordpress-plugins/my-plugin', 'v1.6', \Result\Result::ok('d961c3d')); - - $gitignore = $this->getGitignore(["/wp-content/themes/my-theme\n", - "/wp-content/plugins/my-plugin\n", ], [ - "/wp-content/themes/my-theme\n", - "/wp-content/plugins/my-plugin\n", - ], true, false); - $this->addFactoryNewInstance('\\Dxw\\Whippet\\Git\\Gitignore', $dir, $gitignore); - - $dependencies = new \Dxw\Whippet\Dependencies\Updater( - $this->getFactory(), - $this->getProjectDirectory($dir) - ); - - ob_start(); - $result = $dependencies->updateSingle('plugins/my-plugin'); - $output = ob_get_clean(); - - $this->assertEquals("[Updating plugins/my-plugin]\n", $output); - $this->assertFalse($result->isErr()); - } -} diff --git a/tests/files/whippet_json_test.php b/tests/files/whippet_json_test.php deleted file mode 100644 index 8c2f0ffe..00000000 --- a/tests/files/whippet_json_test.php +++ /dev/null @@ -1,67 +0,0 @@ - [ - ['name' => 'advanced-custom-fields'], - ], - ]); - - $this->assertEquals([ - ['name' => 'advanced-custom-fields'], - ], $whippetJson->getDependencies('plugins')); - } - - public function testGetDependenciesBlank() - { - $whippetJson = new \Dxw\Whippet\Files\WhippetJson([]); - - $this->assertEquals([], $whippetJson->getDependencies('plugins')); - } - - public function testGetSources() - { - $whippetJson = new \Dxw\Whippet\Files\WhippetJson([ - 'src' => [ - 'plugins' => 'git@github.com:dxw-wordpress-plugins/', - ], - ]); - - $this->assertEquals([ - 'plugins' => 'git@github.com:dxw-wordpress-plugins/', - ], $whippetJson->getSources()); - } - - public function testGetDependencyNoMatch() - { - $whippetJson = new \Dxw\Whippet\Files\WhippetJson([ - 'plugins' => [ - [ - 'name' => 'advanced-custom-fields', - 'ref' => 'foobar', - ], - ], - ]); - - $this->assertEquals([], $whippetJson->getDependency('plugins', 'twitget')); - } - - public function testGetDependency() - { - $whippetJson = new \Dxw\Whippet\Files\WhippetJson([ - 'plugins' => [ - [ - 'name' => 'twitget', - 'ref' => 'foobar', - ], - ], - ]); - - $this->assertEquals(['name' => 'twitget', 'ref' => 'foobar'], $whippetJson->getDependency('plugins', 'twitget')); - } -} diff --git a/tests/files/whippet_lock_test.php b/tests/files/whippet_lock_test.php deleted file mode 100644 index d33a8db1..00000000 --- a/tests/files/whippet_lock_test.php +++ /dev/null @@ -1,203 +0,0 @@ - [ - [ - 'name' => 'my-theme', - 'src' => 'git@github.com:dxw-wordpress-themes/my-theme', - 'revision' => '27ba906', - ], - ], - ]); - - $this->assertEquals([ - [ - 'name' => 'my-theme', - 'src' => 'git@github.com:dxw-wordpress-themes/my-theme', - 'revision' => '27ba906', - ], - ], $whippetLock->getDependencies('themes')); - } - - public function testFromStringGetDependencies() - { - $whippetLock = \Dxw\Whippet\Files\WhippetLock::fromString(json_encode([ - 'themes' => [ - [ - 'name' => 'my-theme', - 'src' => 'git@github.com:dxw-wordpress-themes/my-theme', - 'revision' => '27ba906', - ], - ], - ])); - - $this->assertFalse($whippetLock->isErr()); - $this->assertEquals([ - [ - 'name' => 'my-theme', - 'src' => 'git@github.com:dxw-wordpress-themes/my-theme', - 'revision' => '27ba906', - ], - ], $whippetLock->unwrap()->getDependencies('themes')); - } - - public function testFromFileGetDependencies() - { - $dir = $this->getDir(); - - file_put_contents($dir.'/whippet.lock', json_encode([ - 'themes' => [ - [ - 'name' => 'my-theme', - 'src' => 'git@github.com:dxw-wordpress-themes/my-theme', - 'revision' => '27ba906', - ], - ], - ])); - - $whippetLock = \Dxw\Whippet\Files\WhippetLock::fromFile($dir.'/whippet.lock'); - - $this->assertFalse($whippetLock->isErr()); - $this->assertEquals([ - [ - 'name' => 'my-theme', - 'src' => 'git@github.com:dxw-wordpress-themes/my-theme', - 'revision' => '27ba906', - ], - ], $whippetLock->unwrap()->getDependencies('themes')); - } - - public function testGetHash() - { - $whippetLock = new \Dxw\Whippet\Files\WhippetLock([ - 'hash' => '123', - ]); - - $this->assertEquals('123', $whippetLock->getHash()); - } - - public function testGetDependenciesNotSet() - { - $whippetLock = new \Dxw\Whippet\Files\WhippetLock([ - 'themes' => [], - ]); - - $this->assertEquals([], $whippetLock->getDependencies('plugins')); - } - - public function testSetHash() - { - $whippetLock = new \Dxw\Whippet\Files\WhippetLock([]); - - $whippetLock->setHash('123'); - - $this->assertEquals('123', $whippetLock->getHash()); - } - - public function testAddDependency() - { - $whippetLock = new \Dxw\Whippet\Files\WhippetLock([]); - - $whippetLock->addDependency('plugins', 'my-plugin', 'git@github.com/foobar/baz', '123abc'); - $this->assertEquals([ - [ - 'name' => 'my-plugin', - 'src' => 'git@github.com/foobar/baz', - 'revision' => '123abc', - ], - ], $whippetLock->getDependencies('plugins')); - } - - public function testAddDependencyThatAlreadyExists() - { - $whippetLock = new \Dxw\Whippet\Files\WhippetLock([ - 'plugins' => [ - [ - 'name' => 'my-other-plugin', - 'src' => 'git@github.com/foobar/bat', - 'revision' => 'zzz', - ], - [ - 'name' => 'my-plugin', - 'src' => 'git@github.com/foobar/baz', - 'revision' => '456789', - ], - ], - ]); - - $whippetLock->addDependency('plugins', 'my-plugin', 'git@github.com/foobar/baz', '123abc'); - $this->assertEquals([ - [ - 'name' => 'my-other-plugin', - 'src' => 'git@github.com/foobar/bat', - 'revision' => 'zzz', - ], - [ - 'name' => 'my-plugin', - 'src' => 'git@github.com/foobar/baz', - 'revision' => '123abc', - ], - ], $whippetLock->getDependencies('plugins')); - } - - public function testSaveToPath() - { - $dir = $this->getDir(); - - $data = [ - 'foo' => 'bar', - ]; - - $whippetLock = new \Dxw\Whippet\Files\WhippetLock($data); - - $whippetLock->saveToPath($dir.'/my-whippet.lock'); - - $this->assertTrue(file_exists($dir.'/my-whippet.lock')); - $this->assertEquals($data, json_decode(file_get_contents($dir.'/my-whippet.lock'), true)); - } - - public function testSaveToPathPrettyPrinting() - { - $dir = $this->getDir(); - - $data = [ - 'foo' => '/', - ]; - - $whippetLock = new \Dxw\Whippet\Files\WhippetLock($data); - - $whippetLock->saveToPath($dir.'/my-whippet.lock'); - - $this->assertTrue(file_exists($dir.'/my-whippet.lock')); - $this->assertEquals(implode("\n", [ - '{', - ' "foo": "/"', - '}', - '', // Trailing newline - ]), file_get_contents($dir.'/my-whippet.lock'), true); - } - - public function testFromStringInvalid() - { - $output = \Dxw\Whippet\Files\WhippetLock::fromString('this is not json'); - - $this->assertTrue($output->isErr()); - $this->assertEquals('invalid JSON', $output->getErr()); - } - - public function testFromFileNotFound() - { - $dir = $this->getDir(); - - $output = \Dxw\Whippet\Files\WhippetLock::fromFile($dir.'/file-not-found.json'); - - $this->assertTrue($output->isErr()); - $this->assertEquals('file not found', $output->getErr()); - } -} diff --git a/tests/hello_world.rs b/tests/hello_world.rs new file mode 100644 index 00000000..f8fada68 --- /dev/null +++ b/tests/hello_world.rs @@ -0,0 +1,27 @@ +use std::process::Command; + +#[test] +fn test_application_runs() { + let output = Command::new("cargo") + .arg("run") + .arg("--quiet") + .output() + .expect("Failed to execute command"); + + assert!( + output.status.success(), + "Application didn't run successfully" + ); +} + +#[test] +fn test_correct_output() { + let output = Command::new("cargo") + .arg("run") + .arg("--quiet") + .output() + .expect("Failed to execute command"); + + let stdout = String::from_utf8(output.stdout).expect("Output was not valid UTF-8"); + assert_eq!(stdout.trim(), "Hello, world!"); +} diff --git a/tests/plugins_test.php b/tests/plugins_test.php deleted file mode 100644 index 3e00393a..00000000 --- a/tests/plugins_test.php +++ /dev/null @@ -1,92 +0,0 @@ - ['pipe', 'w'], - 2 => ['pipe', 'w'], - ], $pipes, $cwd); - - $this->assertTrue(is_resource($process)); - - $stdout = stream_get_contents($pipes[1]); - fclose($pipes[1]); - $stderr = stream_get_contents($pipes[2]); - fclose($pipes[2]); - - $return = proc_close($process); - - return [$return, $stdout, $stderr]; - } - - public function createTestDir() - { - # Create Whippet repo - $this->dir = $dir = 'tests/plugins-test-dir'; - exec('rm -rf '.$dir); - mkdir($dir); - mkdir($dir.'/config'); - mkdir($dir.'/wp-content'); - mkdir($dir.'/wp-content/plugins'); - file_put_contents($dir.'/.gitignore', "\n"); - file_put_contents($dir.'/plugins', ''); - - # Create a plugin git repo - mkdir($dir.'/git-repo'); - mkdir($dir.'/git-repo/advanced-custom-fields'); - list($return, $stdout, $stderr) = $this->cmd('git init', $dir.'/git-repo/advanced-custom-fields'); - $this->assertEquals(0, $return, 'Error running git command'); - list($return, $stdout, $stderr) = $this->cmd('git commit --allow-empty -m Meow', $dir.'/git-repo/advanced-custom-fields'); - $this->assertEquals(0, $return, 'Error running git command'); - } - - public function testSupportedCommentSyntax() - { - $this->createTestDir(); - file_put_contents($this->dir.'/plugins', "source = \"git-repo/\"\nadvanced-custom-fields=\n; a good comment\n"); - - list($return, $stdout, $stderr) = $this->cmd('../../bin/whippet plugins install', dirname(__DIR__).'/'.$this->dir); - - $this->assertEquals(0, $return); - - $this->assertStringNotContainsString('PHP Fatal error', $stderr); - $this->assertStringNotContainsString('PHP Warning', $stderr); - $this->assertStringNotContainsString('PHP Notice', $stderr); - $this->assertStringNotContainsString('PHP Deprecated', $stderr); - } - - public function testDeprecatedCommentSyntax() - { - $this->createTestDir(); - file_put_contents($this->dir.'/plugins', "source = \"git-repo/\"\nadvanced-custom-fields=\n# a bad comment\n"); - - list($return, $stdout, $stderr) = $this->cmd('../../bin/whippet plugins install', dirname(__DIR__).'/'.$this->dir); - - $this->assertEquals(1, $return); - - $this->assertStringNotContainsString('PHP Fatal error', $stderr); - $this->assertStringNotContainsString('PHP Warning', $stderr); - $this->assertStringNotContainsString('PHP Notice', $stderr); - $this->assertStringNotContainsString('PHP Deprecated', $stderr); - } - - public function testDeprecatedCommentSyntax2() - { - // Add whitespace before the # - $this->createTestDir(); - file_put_contents($this->dir.'/plugins', "source = \"git-repo/\"\nadvanced-custom-fields=\n # a bad comment\n"); - - list($return, $stdout, $stderr) = $this->cmd('../../bin/whippet plugins install', dirname(__DIR__).'/'.$this->dir); - - $this->assertEquals(1, $return); - - $this->assertStringNotContainsString('PHP Fatal error', $stderr); - $this->assertStringNotContainsString('PHP Warning', $stderr); - $this->assertStringNotContainsString('PHP Notice', $stderr); - $this->assertStringNotContainsString('PHP Deprecated', $stderr); - } -} diff --git a/tests/project_directory_test.php b/tests/project_directory_test.php deleted file mode 100644 index 7776b0fe..00000000 --- a/tests/project_directory_test.php +++ /dev/null @@ -1,110 +0,0 @@ -getDir(); - - mkdir($dir.'/wp-content/themes/my-theme'); - touch($dir.'/whippet.json'); - - foreach ([ - $dir.'/wp-content/themes/my-theme', - $dir.'/wp-content/themes', - $dir.'/wp-content', - $dir, - ] as $path) { - $result = \Dxw\Whippet\ProjectDirectory::find($path); - $this->assertFalse($result->isErr()); - $this->assertInstanceOf('\\Dxw\\Whippet\\ProjectDirectory', $result->unwrap()); - $this->assertEquals($dir, $result->unwrap()->__toString()); - } - } - - public function testGetDirectorySuccess2() - { - $dir = $this->getDir(); - - mkdir($dir.'/projects'); - mkdir($dir.'/projects/project1'); - mkdir($dir.'/projects/project1/wp-content/themes/my-theme'); - mkdir($dir.'/projects/project1/wp-content'); - mkdir($dir.'/projects/project1/wp-content/themes'); - mkdir($dir.'/projects/project1/wp-content/themes/my-theme'); - touch($dir.'/projects/project1/whippet.json'); - - foreach ([ - $dir.'/projects/project1/wp-content/themes/my-theme', - $dir.'/projects/project1/wp-content/themes', - $dir.'/projects/project1/wp-content', - $dir.'/projects/project1', - ] as $path) { - $result = \Dxw\Whippet\ProjectDirectory::find($path); - $this->assertFalse($result->isErr()); - $this->assertInstanceOf('\\Dxw\\Whippet\\ProjectDirectory', $result->unwrap()); - $this->assertEquals($dir.'/projects/project1', $result->unwrap()->__toString()); - } - } - - public function testGetDirectoryFailure() - { - $dir = $this->getDir(); - - mkdir($dir.'/projects'); - mkdir($dir.'/projects/project1'); - mkdir($dir.'/projects/project1/wp-content/themes/my-theme'); - mkdir($dir.'/projects/project1/wp-content'); - mkdir($dir.'/projects/project1/wp-content/themes'); - mkdir($dir.'/projects/project1/wp-content/themes/my-theme'); - touch($dir.'/plugins'); - - foreach ([ - $dir.'/projects/project1/wp-content/themes/my-theme', - $dir.'/projects/project1/wp-content/themes', - $dir.'/projects/project1/wp-content', - $dir.'/projects/project1', - ] as $path) { - $result = \Dxw\Whippet\ProjectDirectory::find($path); - $this->assertTrue($result->isErr()); - $this->assertEquals('whippet.json not found', $result->getErr()); - } - } - - public function testGetDirectoryWhippetJson() - { - $dir = $this->getDir(); - - mkdir($dir.'/wp-content/themes/my-theme'); - touch($dir.'/whippet.json'); - - foreach ([ - $dir.'/wp-content/themes/my-theme', - $dir.'/wp-content/themes', - $dir.'/wp-content', - $dir, - ] as $path) { - $result = \Dxw\Whippet\ProjectDirectory::find($path); - $this->assertFalse($result->isErr()); - $this->assertInstanceOf('\\Dxw\\Whippet\\ProjectDirectory', $result->unwrap()); - $this->assertEquals($dir, $result->unwrap()->__toString()); - } - } - - public function testGetDirectoryAvoidPluginsDirectory() - { - $dir = $this->getDir(); - - mkdir($dir.'/wp-content'); - mkdir($dir.'/wp-content/plugins'); - mkdir($dir.'/wp-content/plugins/my-plugin'); - touch($dir.'/whippet.json'); - - $result = \Dxw\Whippet\ProjectDirectory::find($dir.'/wp-content/plugins/my-plugin'); - $this->assertFalse($result->isErr()); - $this->assertInstanceOf('\\Dxw\\Whippet\\ProjectDirectory', $result->unwrap()); - $this->assertEquals($dir, $result->unwrap()->__toString()); - } -} diff --git a/tests/services/inspection_checker_test.php b/tests/services/inspection_checker_test.php deleted file mode 100644 index ba3022ea..00000000 --- a/tests/services/inspection_checker_test.php +++ /dev/null @@ -1,132 +0,0 @@ - 'my-theme', - 'src' => 'git@github.com:dxw-wordpress-themes/my-theme', - 'revision' => '27ba906', - ]; - $checker = new \Dxw\Whippet\Services\InspectionChecker($this->fakeInspectionsApi()); - $result = $checker->check('themes', $my_theme); - - $this->assertFalse($result->isErr()); - $this->assertEquals('', $result->unwrap()); - } - - public function testPluginCallsAPI() - { - $api = $this->fakeInspectionsApi(); - $api->shouldReceive('getInspections') - ->once() - ->with('my-plugin') - ->andReturn(\Result\Result::ok([])); - - $my_plugin = [ - 'name' => 'my-plugin', - 'src' => 'git@github.com:dxw-wordpress-plugins/my-plugin', - 'revision' => '123456', - ]; - $checker = new \Dxw\Whippet\Services\InspectionChecker($api); - $result = $checker->check('plugins', $my_plugin); - $this->assertFalse($result->isErr()); - } - - public function testPluginWithNoInspectionsGeneratesMessage() - { - $api = $this->fakeInspectionsApi(); - $api->shouldReceive('getInspections') - ->andReturn(\Result\Result::ok([])); - - $my_plugin = [ - 'name' => 'my-plugin', - 'src' => 'git@github.com:dxw-wordpress-plugins/my-plugin', - 'revision' => '123456', - ]; - $checker = new \Dxw\Whippet\Services\InspectionChecker($api); - $result = $checker->check('plugins', $my_plugin); - - $this->assertFalse($result->isErr()); - $warning_msg = <<<'EOT' -############################################# -# # -# WARNING: No inspections for this plugin # -# # -############################################# -EOT; - - $this->assertEquals($warning_msg, $result->unwrap()); - } - - public function testPluginWithInspectionsGeneratesMessage() - { - $inspection_ok = $this->fakeInspection(date_create('2015-05-01'), '2.3.4', 'No issues found', 'https://advisories.dxw.com/plugins/another_plugin/'); - $inspection_caution = $this->fakeInspection(date_create('2016-01-23'), '3.0.0', 'Use with caution', 'https://advisories.dxw.com/plugins/another_plugin2/'); - - $api = $this->fakeInspectionsApi(); - $api->shouldReceive('getInspections') - ->andReturn(\Result\Result::ok([$inspection_ok, $inspection_caution])); - - $my_plugin = [ - 'name' => 'my-plugin', - 'src' => 'git@github.com:dxw-wordpress-plugins/my-plugin', - 'revision' => '123456', - ]; - $checker = new \Dxw\Whippet\Services\InspectionChecker($api); - $result = $checker->check('plugins', $my_plugin); - - $this->assertFalse($result->isErr()); - $expected_message = "Inspections for this plugin:\n* 01/05/2015 - 2.3.4 - No issues found - https://advisories.dxw.com/plugins/another_plugin/\n* 23/01/2016 - 3.0.0 - Use with caution - https://advisories.dxw.com/plugins/another_plugin2/"; - $this->assertEquals($expected_message, $result->unwrap()); - } - - public function testUnknownType() - { - $checker = new \Dxw\Whippet\Services\InspectionChecker($this->fakeInspectionsApi()); - $result = $checker->check('hedgehogs', []); - - $this->assertTrue($result->isErr()); - $this->assertEquals("Unknown type 'hedgehogs'", $result->getErr()); - } - - public function testApiError() - { - $api = $this->fakeInspectionsApi(); - $api->shouldReceive('getInspections') - ->andReturn(\Result\Result::err('Something went wrong')); - - $my_plugin = [ - 'name' => 'my-plugin', - 'src' => 'git@github.com:dxw-wordpress-plugins/my-plugin', - 'revision' => '123456', - ]; - $checker = new \Dxw\Whippet\Services\InspectionChecker($api); - $result = $checker->check('plugins', $my_plugin); - - $this->assertTrue($result->isErr()); - $this->assertEquals("Error fetching plugin inspections from API: 'Something went wrong'", $result->getErr()); - } - - private function fakeInspectionsApi() - { - return \Mockery::mock('\\Dxw\\Whippet\\Services\\InspectionsApi'); - } - - # test double - private function fakeInspection($date, $versions, $result, $url) - { - return (object) [ - 'date' => $date, - 'versions' => $versions, - 'result' => $result, - 'url' => $url, - ]; - } -} diff --git a/tests/services/inspections_api_test.php b/tests/services/inspections_api_test.php deleted file mode 100644 index 6e43bfe4..00000000 --- a/tests/services/inspections_api_test.php +++ /dev/null @@ -1,126 +0,0 @@ -fakeJsonApi(); - $json_api->shouldReceive('get') - ->once() - ->with('https://advisories.dxw.com/wp-json/v1/inspections/my-plugin') - ->andReturn(\Result\Result::ok([])); - - $api = new \Dxw\Whippet\Services\InspectionsApi('https://advisories.dxw.com', '/wp-json/v1/inspections/', $json_api); - $result = $api->getInspections('my-plugin'); - $this->assertFalse($result->isErr()); - $this->assertEquals([], $result->unwrap()); - } - - public function testNoInspections() - { - $json_api = $this->fakeJsonApi(); - $json_api->shouldReceive('get')->andReturn(\Result\Result::ok([])); - - $api = new \Dxw\Whippet\Services\InspectionsApi('https://advisories.dxw.com', '/wp-json/v1/inspections/', $json_api); - $result = $api->getInspections('my-plugin'); - - $this->assertFalse($result->isErr()); - $this->assertEquals([], $result->unwrap()); - } - - public function testWithInspections() - { - $response = [ - [ - 'name' => 'Slack', - 'slug' => 'slack', - 'date' => '2016-02-29T17:54:15+00:00', - 'versions' => '1.3.5', - 'url' => 'https://advisories.dxw.com/plugins/slack2/', - 'result' => 'Use with caution' - ], - [ - 'name' => 'Slack', - 'slug' => 'slack', - 'date' => '2015-06-17T24:00:12+00:00', - 'versions' => '1.1.3', - 'url' => 'https://advisories.dxw.com/plugins/slack/', - 'result' => 'No issues found' - ] - ]; - - $json_api = $this->fakeJsonApi(); - $json_api->shouldReceive('get')->andReturn(\Result\Result::ok($response)); - - $api = new \Dxw\Whippet\Services\InspectionsApi('https://advisories.dxw.com', '/wp-json/v1/inspections/', $json_api); - $result = $api->getInspections('my-plugin'); - - $this->assertFalse($result->isErr()); - - $result_body = $result->unwrap(); - $this->assertEquals(2, count($result_body)); - - $inspection = array_shift($result_body); - $this->assertEquals(date_create('2016-02-29T17:54:15'), $inspection->date); - $this->assertEquals('1.3.5', $inspection->versions); - $this->assertEquals('Use with caution', $inspection->result); - $this->assertEquals('https://advisories.dxw.com/plugins/slack2/', $inspection->url); - } - - public function testWithInspectionsWithMissingFields() - { - $response = [ - [ - 'name' => 'Slack', - 'slug' => 'slack', - 'date' => '2016-02-29T17:54:15+00:00', - 'versions' => '1.3.5', - 'url' => 'https://advisories.dxw.com/plugins/slack2/', - 'result' => 'Use with caution' - ], - [ - 'name' => 'Slack', - 'slug' => 'slack', - 'date' => '2015-06-17T24:00:12+00:00', - 'versions' => '1.1.3', - 'url' => 'https://advisories.dxw.com/plugins/slack/', - // missing result - ] - ]; - - $json_api = $this->fakeJsonApi(); - $json_api->shouldReceive('get')->andReturn(\Result\Result::ok($response)); - - $api = new \Dxw\Whippet\Services\InspectionsApi('https://advisories.dxw.com', '/wp-json/v1/inspections/', $json_api); - $result = $api->getInspections('my-plugin'); - - $this->assertTrue($result->isErr()); - - $error_message = $result->getErr(); - $this->assertEquals("Couldn't extract inspections from JSON response", $error_message); - } - - public function testApiError() - { - $json_api = $this->fakeJsonApi(); - $json_api->shouldReceive('get') - ->andReturn(\Result\Result::err('A failure happened')); - - $api = new \Dxw\Whippet\Services\InspectionsApi('https://advisories.dxw.com', '/wp-json/v1/inspections/', $json_api); - $result = $api->getInspections('my-plugin'); - - $this->assertTrue($result->isErr()); - $this->assertEquals('A failure happened', $result->getErr()); - } - - private function fakeJsonApi() - { - $stub = \Mockery::mock('\\Dxw\\Whippet\\Services\\JsonApi'); - return $stub; - } -} diff --git a/tests/services/json_api_test.php b/tests/services/json_api_test.php deleted file mode 100644 index 3adbb908..00000000 --- a/tests/services/json_api_test.php +++ /dev/null @@ -1,132 +0,0 @@ -fakeBaseApi(); - $base_api->shouldReceive('get') - ->once() - ->with('http://apisite.com/api/endpoint') - ->andReturn(\Result\Result::ok('[]')); - - $api = new \Dxw\Whippet\Services\JsonApi($base_api); - $result = $api->get('http://apisite.com/api/endpoint'); - $this->assertFalse($result->isErr()); - $this->assertEquals([], $result->unwrap()); - } - - public function testEmptyResponse() - { - $base_api = $this->fakeBaseApi(); - $base_api->shouldReceive('get')->andReturn(\Result\Result::ok('[]')); - - $api = new \Dxw\Whippet\Services\JsonApi($base_api); - $result = $api->get('http://apisite.com/api/endpoint'); - - $this->assertFalse($result->isErr()); - $this->assertEquals([], $result->unwrap()); - } - - public function testWithInspections() - { - $response_body = '[{"id":2644,"date":"2016-07-13T17:44:23","date_gmt":"2016-07-13T17:44:23","guid":{"rendered":"https:\/\/advisories.dxw.com\/?post_type=plugins&p=2644"},"modified":"2016-08-08T18:26:16","modified_gmt":"2016-08-08T18:26:16","slug":"advanced-custom-fields-table-field","type":"plugins","link":"https:\/\/advisories.dxw.com\/plugins\/advanced-custom-fields-table-field\/","title":{"rendered":"Advanced Custom Fields: Table Field"},"author":5,"_links":{"self":[{"href":"https:\/\/advisories.dxw.com\/wp-json\/wp\/v2\/plugins\/2644"}],"collection":[{"href":"https:\/\/advisories.dxw.com\/wp-json\/wp\/v2\/plugins"}],"about":[{"href":"https:\/\/advisories.dxw.com\/wp-json\/wp\/v2\/types\/plugins"}],"author":[{"embeddable":true,"href":"https:\/\/advisories.dxw.com\/wp-json\/wp\/v2\/users\/5"}],"version-history":[{"href":"https:\/\/advisories.dxw.com\/wp-json\/wp\/v2\/plugins\/2644\/revisions"}],"https:\/\/api.w.org\/attachment":[{"href":"https:\/\/advisories.dxw.com\/wp-json\/wp\/v2\/media?parent=2644"}]}}]'; - $expected_result = [ - [ - "id" => 2644, - "date" => "2016-07-13T17:44:23", - "date_gmt" => "2016-07-13T17:44:23", - "guid" => [ - "rendered" => "https://advisories.dxw.com/?post_type=plugins&p=2644" - ], - "modified" => "2016-08-08T18:26:16", - "modified_gmt" => "2016-08-08T18:26:16", - "slug" => "advanced-custom-fields-table-field", - "type" => "plugins", - "link" => "https://advisories.dxw.com/plugins/advanced-custom-fields-table-field/", - "title" => [ - "rendered" => "Advanced Custom Fields: Table Field" - ], - "author" => 5, - "_links" => [ - "self" => [ - [ - "href" => "https://advisories.dxw.com/wp-json/wp/v2/plugins/2644" - ] - ], - "collection" => [ - [ - "href" => "https://advisories.dxw.com/wp-json/wp/v2/plugins" - ] - ], - "about" => [ - [ - "href" => "https://advisories.dxw.com/wp-json/wp/v2/types/plugins" - ] - ], - "author" => [ - [ - "embeddable" => true, - "href" => "https://advisories.dxw.com/wp-json/wp/v2/users/5" - ] - ], - "version-history" => [ - [ - "href" => "https://advisories.dxw.com/wp-json/wp/v2/plugins/2644/revisions" - ] - ], - "https://api.w.org/attachment" => [ - [ - "href" => "https://advisories.dxw.com/wp-json/wp/v2/media?parent=2644" - ] - ] - ] - ] - ]; - - $base_api = $this->fakeBaseApi(); - $base_api->shouldReceive('get')->andReturn(\Result\Result::ok($response_body)); - - $api = new \Dxw\Whippet\Services\JsonApi($base_api); - $result = $api->get('https://advisories.dxw.com/api/endpoint'); - - $this->assertFalse($result->isErr()); - $this->assertEquals($expected_result, $result->unwrap()); - } - - public function testInvalidJSON() - { - $base_api = $this->fakeBaseApi(); - $base_api->shouldReceive('get') - ->andReturn(\Result\Result::ok('a webpage')); - - $api = new \Dxw\Whippet\Services\JsonApi($base_api); - $result = $api->get('http://apisite.com/api/endpoint'); - - $this->assertTrue($result->isErr()); - $this->assertEquals('Failed to parse response body as JSON when requesting http://apisite.com/api/endpoint', $result->getErr()); - } - - public function testApiError() - { - $base_api = $this->fakeBaseApi(); - $base_api->shouldReceive('get') - ->andReturn(\Result\Result::err('A failure happened')); - - $api = new \Dxw\Whippet\Services\JsonApi($base_api); - $result = $api->get('http://apisite.com/api/endpoint'); - - $this->assertTrue($result->isErr()); - $this->assertEquals('A failure happened', $result->getErr()); - } - - private function fakeBaseApi() - { - return \Mockery::mock('\\Dxw\\Whippet\\Services\\BaseApi'); - } -} diff --git a/vendor.phar b/vendor.phar deleted file mode 100644 index 1bee6a19..00000000 Binary files a/vendor.phar and /dev/null differ