diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml new file mode 100644 index 0000000..8ca7d16 --- /dev/null +++ b/.github/FUNDING.yml @@ -0,0 +1,2 @@ +# These are supported funding model platforms +github: [phpgt] \ No newline at end of file diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 0000000..307abf3 --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,12 @@ +version: 2 +updates: + - package-ecosystem: composer + directory: "/" + schedule: + interval: daily + open-pull-requests-limit: 10 + ignore: + - dependency-name: phpunit/phpunit + update-types: ["version-update:semver-patch"] + - dependency-name: phpstan/phpstan + update-types: ["version-update:semver-patch"] diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 27cc5d8..a06a079 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -1,66 +1,181 @@ name: CI -on: [push] +on: [push, pull_request] + +permissions: + contents: read + actions: read + id-token: none jobs: composer: runs-on: ubuntu-latest + strategy: + matrix: + php: [ 8.3, 8.4 ] steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 - name: Cache Composer dependencies - uses: actions/cache@v2 + uses: actions/cache@v4 with: path: /tmp/composer-cache - key: ${{ runner.os }}-${{ hashFiles('**/composer.lock') }} + key: ${{ runner.os }}-${{ matrix.php }}-${{ hashFiles('**/composer.lock') }} - - uses: php-actions/composer@v5 + - name: Composer install + uses: php-actions/composer@v6 + with: + php_version: ${{ matrix.php }} - name: Archive build - run: mkdir /tmp/github-actions/ && tar -cvf /tmp/github-actions/build.tar ./ + run: mkdir /tmp/github-actions/ && tar --exclude=".git" -cvf /tmp/github-actions/build.tar ./ - name: Upload build archive for test runners - uses: actions/upload-artifact@v2 + uses: actions/upload-artifact@v4 with: - name: build-artifact + name: build-artifact-${{ matrix.php }} path: /tmp/github-actions phpunit: runs-on: ubuntu-latest - needs: [composer] + needs: [ composer ] + strategy: + matrix: + php: [ 8.3, 8.4 ] + + outputs: + coverage: ${{ steps.store-coverage.outputs.coverage_text }} steps: - - uses: actions/download-artifact@v2 + - uses: actions/download-artifact@v4 with: - name: build-artifact + name: build-artifact-${{ matrix.php }} path: /tmp/github-actions - name: Extract build archive run: tar -xvf /tmp/github-actions/build.tar ./ - name: PHP Unit tests - uses: php-actions/phpunit@v2 + uses: php-actions/phpunit@v4 + env: + XDEBUG_MODE: cover with: - php_version: 8.0 + php_version: ${{ matrix.php }} php_extensions: xdebug - configuration: test/phpunit/phpunit.xml - bootstrap: vendor/autoload.php + coverage_text: _coverage/coverage.txt + coverage_clover: _coverage/clover.xml + + - name: Store coverage data + uses: actions/upload-artifact@v4 + with: + name: code-coverage-${{ matrix.php }}-${{ github.run_number }} + path: _coverage + + coverage: + runs-on: ubuntu-latest + needs: [ phpunit ] + strategy: + matrix: + php: [ 8.3, 8.4 ] + + steps: + - uses: actions/checkout@v4 + + - uses: actions/download-artifact@v4 + with: + name: code-coverage-${{ matrix.php }}-${{ github.run_number }} + path: _coverage + + - name: Output coverage + run: cat "_coverage/coverage.txt" + + - name: Upload to Codecov + uses: codecov/codecov-action@v5 phpstan: runs-on: ubuntu-latest - needs: [composer] + needs: [ composer ] + strategy: + matrix: + php: [ 8.3, 8.4 ] steps: - - uses: actions/download-artifact@v2 + - uses: actions/download-artifact@v4 with: - name: build-artifact + name: build-artifact-${{ matrix.php }} path: /tmp/github-actions - name: Extract build archive run: tar -xvf /tmp/github-actions/build.tar ./ - name: PHP Static Analysis - uses: php-actions/phpstan@v2 + uses: php-actions/phpstan@v3 + with: + php_version: ${{ matrix.php }} + path: src/ + + phpmd: + runs-on: ubuntu-latest + needs: [ composer ] + strategy: + matrix: + php: [ 8.3, 8.4 ] + + steps: + - uses: actions/download-artifact@v4 + with: + name: build-artifact-${{ matrix.php }} + path: /tmp/github-actions + + - name: Extract build archive + run: tar -xvf /tmp/github-actions/build.tar ./ + + - name: PHP Mess Detector + uses: php-actions/phpmd@v1 + with: + php_version: ${{ matrix.php }} + path: src/ + output: text + ruleset: phpmd.xml + + phpcs: + runs-on: ubuntu-latest + needs: [ composer ] + strategy: + matrix: + php: [ 8.3, 8.4 ] + + steps: + - uses: actions/download-artifact@v4 + with: + name: build-artifact-${{ matrix.php }} + path: /tmp/github-actions + + - name: Extract build archive + run: tar -xvf /tmp/github-actions/build.tar ./ + + - name: PHP Code Sniffer + uses: php-actions/phpcs@v1 with: - path: src/ \ No newline at end of file + php_version: ${{ matrix.php }} + path: src/ + standard: phpcs.xml + + remove_old_artifacts: + runs-on: ubuntu-latest + + permissions: + actions: write + + steps: + - name: Remove old artifacts for prior workflow runs on this repository + env: + GH_TOKEN: ${{ github.token }} + run: | + gh api "/repos/${{ github.repository }}/actions/artifacts" | jq ".artifacts[] | select(.name | startswith(\"build-artifact\")) | .id" > artifact-id-list.txt + while read id + do + echo -n "Deleting artifact ID $id ... " + gh api --method DELETE /repos/${{ github.repository }}/actions/artifacts/$id && echo "Done" + done getFileUpload("photo")`, `$input->getDateTime("date-of-birth")`, and `$input->getMultipleString("pizza-topping")`. *** PHP.Gt/Input build status - + PHP.Gt/Input code quality - + PHP.Gt/Input code coverage @@ -31,81 +31,73 @@ Example usage ```html
-

Buy this amazing product

+

User Profile

- - - + - +
``` ```php do("pay") - ->call([$payment, "processCard"]); - -// Storing user's shipping data doesn't need to know credit card information: -$input->do("pay") - ->with("name", "address") - ->call("processShipping"); - -function processShipping(string $name, string $address) { - setUsername($name); - storeNameAddress($name, $address); +$profile->update( + $profileId, +// Use type-safe getters to help write maintainable code. + $input->getString("name"), + $input->getInt("age"), +); + +// Handle multiple values with type safety. +foreach($input->getMultipleString("interest") as $interest) { + $profile->addInterest($interest); } -``` - -Why? ----- -This library's primary objective is to provide automatic application security, so only the code that has authorisation to read sensitive user input can do so. - -The encapsulation of user input promotes the benefits of object oriented programming. Rather than having all user input available in global scope, the developer must decide which code receives the user input. - -The purpose is to enhance security, and prevent bad coding patterns such as changing the flow of logic depending on whether a particular query string parameter is set. - -How? ----- - -Once an instance of Input is created, all global variables can be unset completely, preventing ad-hoc usage and possible alteration from unknown sources. This is done using `Gt\Input\Globals::unset()`. +// Handle file uploads with a FileUpload object. +$photoUpload = $input->getFile("photo"); +if($photoUpload instanceof FailedFileUpload) { + // Handle a failed upload here. +} -Note that the automatic security feature is being released as [version 2][v2] and is not currently available in the library, but will be released when ready with no backwards breaking changes. +$photoUpload->moveTo("data/upload/$profileId.jpg"); +``` -The page can be secured by injecting the public key into the page. If your application uses a [DOM document][dom], the forms can be injected for you with `Gt\Input\Security\Injector`, otherwise generate your own using `Gt\Input\Security\Key` to create [secure data fields][secure-data-fields]. +Features at a glance +-------------------- -A small amount of JavaScript is used to secure user input before being sent by the browser. The JavaScript is within the `src/JavaScript` directory. ++ Type-safe getters, implementing the [TypeSafeGetter][tsg] interface. ++ Typed `multiple` getters, for working with checkboxes, multi-select elements or multiple file uploads. ++ "do" callback functions - hook up callbacks to button presses (implemented automatically in WebEngine applications). ++ "when" triggers - execute callbacks when certain user input is present. ++ `FileUploadInputData` class for easy file uploads, including functions such as `moveTo()`, `getOriginalName()`, etc. ++ Coming soon: working with huge files by streaming them to PHP, efficiently managing memory in the process. -If JavaScript fails to execute or is forgotten, PHP execution will halt to prevent unsecured input being available. +[tsg]: https://php.gt/typesafegetter -What about `php://input`? -------------------------- +# Proudly sponsored by -The PHP input stream can be accessed to read raw post data, and this isn't changed by this library. However, when using [secure data fields][secure-data-fields] the user input is encrypted with your application's secret key before it is sent from the user's web browser. The fields are still available to code that reads the input stream, but will be encrypted. +[JetBrains Open Source sponsorship program](https://www.jetbrains.com/community/opensource/) -[v2]: https://github.com/PhpGt/Input/issues?q=is%3Aopen+is%3Aissue+milestone%3Av2 -[dom]: https://php.gt/dom -[secure-data-fields]: https://php.gt/input/security +[![JetBrains logo.](https://resources.jetbrains.com/storage/products/company/brand/logos/jetbrains.svg)](https://www.jetbrains.com/community/opensource/) diff --git a/SECURITY.md b/SECURITY.md new file mode 100644 index 0000000..ee9f073 --- /dev/null +++ b/SECURITY.md @@ -0,0 +1,25 @@ +# Security Policy + +## Supported Versions + +All MAJOR versions of this package will receive security updates for **two years after the next major version is released**. For example, if version 4.0.0 is released, version 3.x will continue receiving security updates for two years from that date. + +Versions outside this window are considered end-of-life and will no longer receive updates, even for critical vulnerabilities. + +## Reporting a Vulnerability + +If you discover a security issue, please report it using GitHub's [**"Report a vulnerability"** feature](../../security/advisories/new) under the **Security** tab of this repository. + +When reporting, please include the following information to help us investigate quickly and thoroughly: + +- A clear description of the vulnerability and what part of the code it affects. +- Steps to reproduce the issue, ideally including: + - The affected version + - A code snippet or minimal test case + - The expected vs. actual behavior +- If applicable, an explanation of potential impact or severity. +- Any suggested mitigations or patches (optional, but appreciated). + +Please do not disclose the vulnerability publicly until we've had a chance to investigate and publish a fix. + +We appreciate responsible disclosure and are committed to resolving issues promptly. diff --git a/composer.json b/composer.json index 633f36d..1d3a171 100644 --- a/composer.json +++ b/composer.json @@ -4,12 +4,16 @@ "license": "MIT", "require": { - "phpgt/http": "1.*" + "php": ">=8.3", + "phpgt/http": "1.*", + "phpgt/json": "^2.1" }, "require-dev": { - "phpunit/phpunit": "9.*", - "phpstan/phpstan": ">=0.12.64" + "phpstan/phpstan": "^1.10", + "phpunit/phpunit": "^10.5", + "phpmd/phpmd": "^2.13", + "squizlabs/php_codesniffer": "^3.7" }, "autoload": { @@ -21,5 +25,12 @@ "psr-4": { "Gt\\Input\\Test\\": "./test/phpunit" } - } -} \ No newline at end of file + }, + + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/PhpGt" + } + ] +} diff --git a/composer.lock b/composer.lock index c8a5f89..40100c0 100644 --- a/composer.lock +++ b/composer.lock @@ -4,27 +4,178 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "63d79b4aa22bd6a8d243e9c69d60bd27", + "content-hash": "2b25525793bab1c67e83d0dc7710d967", "packages": [ + { + "name": "justinrainbow/json-schema", + "version": "6.4.1", + "source": { + "type": "git", + "url": "https://github.com/jsonrainbow/json-schema.git", + "reference": "35d262c94959571e8736db1e5c9bc36ab94ae900" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/jsonrainbow/json-schema/zipball/35d262c94959571e8736db1e5c9bc36ab94ae900", + "reference": "35d262c94959571e8736db1e5c9bc36ab94ae900", + "shasum": "" + }, + "require": { + "ext-json": "*", + "marc-mabe/php-enum": "^4.0", + "php": "^7.2 || ^8.0" + }, + "require-dev": { + "friendsofphp/php-cs-fixer": "3.3.0", + "json-schema/json-schema-test-suite": "1.2.0", + "marc-mabe/php-enum-phpstan": "^2.0", + "phpspec/prophecy": "^1.19", + "phpstan/phpstan": "^1.12", + "phpunit/phpunit": "^8.5" + }, + "bin": [ + "bin/validate-json" + ], + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "6.x-dev" + } + }, + "autoload": { + "psr-4": { + "JsonSchema\\": "src/JsonSchema/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Bruno Prieto Reis", + "email": "bruno.p.reis@gmail.com" + }, + { + "name": "Justin Rainbow", + "email": "justin.rainbow@gmail.com" + }, + { + "name": "Igor Wiedler", + "email": "igor@wiedler.ch" + }, + { + "name": "Robert Schönthal", + "email": "seroscho@googlemail.com" + } + ], + "description": "A library to validate a json schema.", + "homepage": "https://github.com/jsonrainbow/json-schema", + "keywords": [ + "json", + "schema" + ], + "support": { + "issues": "https://github.com/jsonrainbow/json-schema/issues", + "source": "https://github.com/jsonrainbow/json-schema/tree/6.4.1" + }, + "time": "2025-04-04T13:08:07+00:00" + }, + { + "name": "marc-mabe/php-enum", + "version": "v4.7.1", + "source": { + "type": "git", + "url": "https://github.com/marc-mabe/php-enum.git", + "reference": "7159809e5cfa041dca28e61f7f7ae58063aae8ed" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/marc-mabe/php-enum/zipball/7159809e5cfa041dca28e61f7f7ae58063aae8ed", + "reference": "7159809e5cfa041dca28e61f7f7ae58063aae8ed", + "shasum": "" + }, + "require": { + "ext-reflection": "*", + "php": "^7.1 | ^8.0" + }, + "require-dev": { + "phpbench/phpbench": "^0.16.10 || ^1.0.4", + "phpstan/phpstan": "^1.3.1", + "phpunit/phpunit": "^7.5.20 | ^8.5.22 | ^9.5.11", + "vimeo/psalm": "^4.17.0 | ^5.26.1" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-3.x": "3.2-dev", + "dev-master": "4.7-dev" + } + }, + "autoload": { + "psr-4": { + "MabeEnum\\": "src/" + }, + "classmap": [ + "stubs/Stringable.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Marc Bennewitz", + "email": "dev@mabe.berlin", + "homepage": "https://mabe.berlin/", + "role": "Lead" + } + ], + "description": "Simple and fast implementation of enumerations with native PHP", + "homepage": "https://github.com/marc-mabe/php-enum", + "keywords": [ + "enum", + "enum-map", + "enum-set", + "enumeration", + "enumerator", + "enummap", + "enumset", + "map", + "set", + "type", + "type-hint", + "typehint" + ], + "support": { + "issues": "https://github.com/marc-mabe/php-enum/issues", + "source": "https://github.com/marc-mabe/php-enum/tree/v4.7.1" + }, + "time": "2024-11-28T04:54:44+00:00" + }, { "name": "phpgt/cookie", - "version": "v1.0.2", + "version": "v1.0.3", "source": { "type": "git", - "url": "https://github.com/PhpGt/Cookie.git", - "reference": "dd811b6f04becc7c1f8524d84ad02e4635f4a94e" + "url": "https://github.com/phpgt/Cookie.git", + "reference": "6c80638745ce4538aa397843e7c0b760b60a08c5" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/PhpGt/Cookie/zipball/dd811b6f04becc7c1f8524d84ad02e4635f4a94e", - "reference": "dd811b6f04becc7c1f8524d84ad02e4635f4a94e", + "url": "https://api.github.com/repos/phpgt/Cookie/zipball/6c80638745ce4538aa397843e7c0b760b60a08c5", + "reference": "6c80638745ce4538aa397843e7c0b760b60a08c5", "shasum": "" }, "require": { - "php": ">=7.2" + "php": ">=8.1" }, "require-dev": { - "phpunit/phpunit": "8.*" + "phpmd/phpmd": "^2.13", + "phpstan/phpstan": "^1.10", + "phpunit/phpunit": "^10.1", + "squizlabs/php_codesniffer": "^3.7" }, "type": "library", "autoload": { @@ -44,10 +195,70 @@ ], "description": "Object oriented cookie handler.", "support": { - "issues": "https://github.com/PhpGt/Cookie/issues", - "source": "https://github.com/PhpGt/Cookie/tree/v1.0.2" + "issues": "https://github.com/phpgt/Cookie/issues", + "source": "https://github.com/phpgt/Cookie/tree/v1.0.3" + }, + "funding": [ + { + "url": "https://github.com/sponsors/PhpGt", + "type": "github" + } + ], + "time": "2025-03-07T17:42:38+00:00" + }, + { + "name": "phpgt/dataobject", + "version": "v1.1.0", + "source": { + "type": "git", + "url": "https://github.com/PhpGt/DataObject.git", + "reference": "534b593617e40f62ba5ea5a399797e4b0107a40a" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/PhpGt/DataObject/zipball/534b593617e40f62ba5ea5a399797e4b0107a40a", + "reference": "534b593617e40f62ba5ea5a399797e4b0107a40a", + "shasum": "" + }, + "require": { + "ext-json": "*", + "php": ">=8.1", + "phpgt/typesafegetter": "^1.3" + }, + "require-dev": { + "phpmd/phpmd": "^2.13", + "phpstan/phpstan": "^1.10", + "phpunit/phpunit": "^10.1", + "squizlabs/php_codesniffer": "^3.7" + }, + "type": "library", + "autoload": { + "psr-4": { + "Gt\\DataObject\\": "./src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Greg Bowler", + "email": "greg.bowler@g105b.com" + } + ], + "description": " Structured, type-safe, immutable data transfer.", + "support": { + "issues": "https://github.com/PhpGt/DataObject/issues", + "source": "https://github.com/PhpGt/DataObject/tree/v1.1.0" }, - "time": "2019-07-17T20:11:11+00:00" + "funding": [ + { + "url": "https://github.com/phpgt", + "type": "github" + } + ], + "time": "2025-02-14T16:43:15+00:00" }, { "name": "phpgt/http", @@ -90,27 +301,134 @@ }, "time": "2020-06-16T13:13:25+00:00" }, + { + "name": "phpgt/json", + "version": "v2.1.0", + "source": { + "type": "git", + "url": "https://github.com/PhpGt/Json.git", + "reference": "ba557c441a01e32a5040380556ee6e7e59599dfd" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/PhpGt/Json/zipball/ba557c441a01e32a5040380556ee6e7e59599dfd", + "reference": "ba557c441a01e32a5040380556ee6e7e59599dfd", + "shasum": "" + }, + "require": { + "ext-json": "*", + "justinrainbow/json-schema": "^6.1", + "php": ">=8.1", + "phpgt/dataobject": "^1.1" + }, + "require-dev": { + "phpmd/phpmd": "^2.13", + "phpstan/phpstan": "^1.10", + "phpunit/phpunit": "^10.1", + "squizlabs/php_codesniffer": "^3.7" + }, + "type": "library", + "autoload": { + "psr-4": { + "Gt\\Json\\": "./src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Greg Bowler", + "email": "greg.bowler@g105b.com" + } + ], + "description": " Structured, type-safe, immutable JSON objects.", + "support": { + "issues": "https://github.com/PhpGt/Json/issues", + "source": "https://github.com/PhpGt/Json/tree/v2.1.0" + }, + "funding": [ + { + "url": "https://github.com/sponsors/PhpGt", + "type": "github" + } + ], + "time": "2025-03-01T16:17:53+00:00" + }, + { + "name": "phpgt/typesafegetter", + "version": "v1.3.2", + "source": { + "type": "git", + "url": "https://github.com/PhpGt/TypeSafeGetter.git", + "reference": "f760c05a37b1cc188dcbf800c5fdfab8a926b4b0" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/PhpGt/TypeSafeGetter/zipball/f760c05a37b1cc188dcbf800c5fdfab8a926b4b0", + "reference": "f760c05a37b1cc188dcbf800c5fdfab8a926b4b0", + "shasum": "" + }, + "require": { + "php": ">=8.0" + }, + "require-dev": { + "phpmd/phpmd": "^2.13", + "phpstan/phpstan": "^1.10", + "phpunit/phpunit": "^10.1", + "squizlabs/php_codesniffer": "^3.7" + }, + "type": "library", + "autoload": { + "psr-4": { + "Gt\\TypeSafeGetter\\": "./src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Greg Bowler", + "email": "greg.bowler@g105b.com" + } + ], + "description": "An interface for objects that expose type-safe getter methods.", + "support": { + "issues": "https://github.com/PhpGt/TypeSafeGetter/issues", + "source": "https://github.com/PhpGt/TypeSafeGetter/tree/v1.3.2" + }, + "funding": [ + { + "url": "https://github.com/sponsors/PhpGt", + "type": "github" + } + ], + "time": "2023-04-28T14:42:27+00:00" + }, { "name": "psr/http-message", - "version": "1.0.1", + "version": "1.1", "source": { "type": "git", "url": "https://github.com/php-fig/http-message.git", - "reference": "f6561bf28d520154e4b0ec72be95418abe6d9363" + "reference": "cb6ce4845ce34a8ad9e68117c10ee90a29919eba" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/php-fig/http-message/zipball/f6561bf28d520154e4b0ec72be95418abe6d9363", - "reference": "f6561bf28d520154e4b0ec72be95418abe6d9363", + "url": "https://api.github.com/repos/php-fig/http-message/zipball/cb6ce4845ce34a8ad9e68117c10ee90a29919eba", + "reference": "cb6ce4845ce34a8ad9e68117c10ee90a29919eba", "shasum": "" }, "require": { - "php": ">=5.3.0" + "php": "^7.2 || ^8.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.0.x-dev" + "dev-master": "1.1.x-dev" } }, "autoload": { @@ -139,9 +457,9 @@ "response" ], "support": { - "source": "https://github.com/php-fig/http-message/tree/master" + "source": "https://github.com/php-fig/http-message/tree/1.1" }, - "time": "2016-08-06T14:39:51+00:00" + "time": "2023-04-04T09:50:52+00:00" }, { "name": "willdurand/negotiation", @@ -202,35 +520,44 @@ ], "packages-dev": [ { - "name": "doctrine/instantiator", - "version": "1.4.0", + "name": "composer/pcre", + "version": "3.3.2", "source": { "type": "git", - "url": "https://github.com/doctrine/instantiator.git", - "reference": "d56bf6102915de5702778fe20f2de3b2fe570b5b" + "url": "https://github.com/composer/pcre.git", + "reference": "b2bed4734f0cc156ee1fe9c0da2550420d99a21e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/instantiator/zipball/d56bf6102915de5702778fe20f2de3b2fe570b5b", - "reference": "d56bf6102915de5702778fe20f2de3b2fe570b5b", + "url": "https://api.github.com/repos/composer/pcre/zipball/b2bed4734f0cc156ee1fe9c0da2550420d99a21e", + "reference": "b2bed4734f0cc156ee1fe9c0da2550420d99a21e", "shasum": "" }, "require": { - "php": "^7.1 || ^8.0" + "php": "^7.4 || ^8.0" + }, + "conflict": { + "phpstan/phpstan": "<1.11.10" }, "require-dev": { - "doctrine/coding-standard": "^8.0", - "ext-pdo": "*", - "ext-phar": "*", - "phpbench/phpbench": "^0.13 || 1.0.0-alpha2", - "phpstan/phpstan": "^0.12", - "phpstan/phpstan-phpunit": "^0.12", - "phpunit/phpunit": "^7.0 || ^8.0 || ^9.0" + "phpstan/phpstan": "^1.12 || ^2", + "phpstan/phpstan-strict-rules": "^1 || ^2", + "phpunit/phpunit": "^8 || ^9" }, "type": "library", + "extra": { + "phpstan": { + "includes": [ + "extension.neon" + ] + }, + "branch-alias": { + "dev-main": "3.x-dev" + } + }, "autoload": { "psr-4": { - "Doctrine\\Instantiator\\": "src/Doctrine/Instantiator/" + "Composer\\Pcre\\": "src" } }, "notification-url": "https://packagist.org/downloads/", @@ -239,129 +566,200 @@ ], "authors": [ { - "name": "Marco Pivetta", - "email": "ocramius@gmail.com", - "homepage": "https://ocramius.github.io/" + "name": "Jordi Boggiano", + "email": "j.boggiano@seld.be", + "homepage": "http://seld.be/" } ], - "description": "A small, lightweight utility to instantiate objects in PHP without invoking their constructors", - "homepage": "https://www.doctrine-project.org/projects/instantiator.html", + "description": "PCRE wrapping library that offers type-safe preg_* replacements.", "keywords": [ - "constructor", - "instantiate" + "PCRE", + "preg", + "regex", + "regular expression" ], "support": { - "issues": "https://github.com/doctrine/instantiator/issues", - "source": "https://github.com/doctrine/instantiator/tree/1.4.0" + "issues": "https://github.com/composer/pcre/issues", + "source": "https://github.com/composer/pcre/tree/3.3.2" }, "funding": [ { - "url": "https://www.doctrine-project.org/sponsorship.html", + "url": "https://packagist.com/", "type": "custom" }, { - "url": "https://www.patreon.com/phpdoctrine", - "type": "patreon" + "url": "https://github.com/composer", + "type": "github" }, { - "url": "https://tidelift.com/funding/github/packagist/doctrine%2Finstantiator", + "url": "https://tidelift.com/funding/github/packagist/composer/composer", "type": "tidelift" } ], - "time": "2020-11-10T18:47:58+00:00" + "time": "2024-11-12T16:29:46+00:00" }, { - "name": "myclabs/deep-copy", - "version": "1.10.2", + "name": "composer/xdebug-handler", + "version": "3.0.5", "source": { "type": "git", - "url": "https://github.com/myclabs/DeepCopy.git", - "reference": "776f831124e9c62e1a2c601ecc52e776d8bb7220" + "url": "https://github.com/composer/xdebug-handler.git", + "reference": "6c1925561632e83d60a44492e0b344cf48ab85ef" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/776f831124e9c62e1a2c601ecc52e776d8bb7220", - "reference": "776f831124e9c62e1a2c601ecc52e776d8bb7220", + "url": "https://api.github.com/repos/composer/xdebug-handler/zipball/6c1925561632e83d60a44492e0b344cf48ab85ef", + "reference": "6c1925561632e83d60a44492e0b344cf48ab85ef", "shasum": "" }, "require": { - "php": "^7.1 || ^8.0" - }, - "replace": { - "myclabs/deep-copy": "self.version" + "composer/pcre": "^1 || ^2 || ^3", + "php": "^7.2.5 || ^8.0", + "psr/log": "^1 || ^2 || ^3" }, "require-dev": { - "doctrine/collections": "^1.0", - "doctrine/common": "^2.6", - "phpunit/phpunit": "^7.1" + "phpstan/phpstan": "^1.0", + "phpstan/phpstan-strict-rules": "^1.1", + "phpunit/phpunit": "^8.5 || ^9.6 || ^10.5" }, "type": "library", "autoload": { "psr-4": { - "DeepCopy\\": "src/DeepCopy/" - }, - "files": [ - "src/DeepCopy/deep_copy.php" - ] + "Composer\\XdebugHandler\\": "src" + } }, "notification-url": "https://packagist.org/downloads/", "license": [ "MIT" ], - "description": "Create deep copies (clones) of your objects", + "authors": [ + { + "name": "John Stevenson", + "email": "john-stevenson@blueyonder.co.uk" + } + ], + "description": "Restarts a process without Xdebug.", "keywords": [ - "clone", - "copy", - "duplicate", - "object", - "object graph" + "Xdebug", + "performance" ], "support": { - "issues": "https://github.com/myclabs/DeepCopy/issues", - "source": "https://github.com/myclabs/DeepCopy/tree/1.10.2" + "irc": "ircs://irc.libera.chat:6697/composer", + "issues": "https://github.com/composer/xdebug-handler/issues", + "source": "https://github.com/composer/xdebug-handler/tree/3.0.5" }, "funding": [ { - "url": "https://tidelift.com/funding/github/packagist/myclabs/deep-copy", + "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": "2020-11-13T09:40:50+00:00" + "time": "2024-05-06T16:37:16+00:00" }, { - "name": "nikic/php-parser", - "version": "v4.10.4", + "name": "myclabs/deep-copy", + "version": "1.13.1", "source": { "type": "git", - "url": "https://github.com/nikic/PHP-Parser.git", - "reference": "c6d052fc58cb876152f89f532b95a8d7907e7f0e" + "url": "https://github.com/myclabs/DeepCopy.git", + "reference": "1720ddd719e16cf0db4eb1c6eca108031636d46c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/c6d052fc58cb876152f89f532b95a8d7907e7f0e", - "reference": "c6d052fc58cb876152f89f532b95a8d7907e7f0e", + "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/1720ddd719e16cf0db4eb1c6eca108031636d46c", + "reference": "1720ddd719e16cf0db4eb1c6eca108031636d46c", "shasum": "" }, "require": { - "ext-tokenizer": "*", - "php": ">=7.0" + "php": "^7.1 || ^8.0" + }, + "conflict": { + "doctrine/collections": "<1.6.8", + "doctrine/common": "<2.13.3 || >=3 <3.2.2" }, "require-dev": { - "ircmaxell/php-yacc": "^0.0.7", - "phpunit/phpunit": "^6.5 || ^7.0 || ^8.0 || ^9.0" + "doctrine/collections": "^1.6.8", + "doctrine/common": "^2.13.3 || ^3.2.2", + "phpspec/prophecy": "^1.10", + "phpunit/phpunit": "^7.5.20 || ^8.5.23 || ^9.5.13" }, - "bin": [ - "bin/php-parse" - ], "type": "library", - "extra": { - "branch-alias": { - "dev-master": "4.9-dev" - } - }, "autoload": { + "files": [ + "src/DeepCopy/deep_copy.php" + ], "psr-4": { - "PhpParser\\": "lib/PhpParser" + "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.13.1" + }, + "funding": [ + { + "url": "https://tidelift.com/funding/github/packagist/myclabs/deep-copy", + "type": "tidelift" + } + ], + "time": "2025-04-29T12:36:36+00:00" + }, + { + "name": "nikic/php-parser", + "version": "v5.4.0", + "source": { + "type": "git", + "url": "https://github.com/nikic/PHP-Parser.git", + "reference": "447a020a1f875a434d62f2a401f53b82a396e494" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/447a020a1f875a434d62f2a401f53b82a396e494", + "reference": "447a020a1f875a434d62f2a401f53b82a396e494", + "shasum": "" + }, + "require": { + "ext-ctype": "*", + "ext-json": "*", + "ext-tokenizer": "*", + "php": ">=7.4" + }, + "require-dev": { + "ircmaxell/php-yacc": "^0.0.7", + "phpunit/phpunit": "^9.0" + }, + "bin": [ + "bin/php-parse" + ], + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "5.0-dev" + } + }, + "autoload": { + "psr-4": { + "PhpParser\\": "lib/PhpParser" } }, "notification-url": "https://packagist.org/downloads/", @@ -380,26 +778,90 @@ ], "support": { "issues": "https://github.com/nikic/PHP-Parser/issues", - "source": "https://github.com/nikic/PHP-Parser/tree/v4.10.4" + "source": "https://github.com/nikic/PHP-Parser/tree/v5.4.0" + }, + "time": "2024-12-30T11:07:19+00:00" + }, + { + "name": "pdepend/pdepend", + "version": "2.16.2", + "source": { + "type": "git", + "url": "https://github.com/pdepend/pdepend.git", + "reference": "f942b208dc2a0868454d01b29f0c75bbcfc6ed58" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/pdepend/pdepend/zipball/f942b208dc2a0868454d01b29f0c75bbcfc6ed58", + "reference": "f942b208dc2a0868454d01b29f0c75bbcfc6ed58", + "shasum": "" + }, + "require": { + "php": ">=5.3.7", + "symfony/config": "^2.3.0|^3|^4|^5|^6.0|^7.0", + "symfony/dependency-injection": "^2.3.0|^3|^4|^5|^6.0|^7.0", + "symfony/filesystem": "^2.3.0|^3|^4|^5|^6.0|^7.0", + "symfony/polyfill-mbstring": "^1.19" + }, + "require-dev": { + "easy-doc/easy-doc": "0.0.0|^1.2.3", + "gregwar/rst": "^1.0", + "squizlabs/php_codesniffer": "^2.0.0" + }, + "bin": [ + "src/bin/pdepend" + ], + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.x-dev" + } + }, + "autoload": { + "psr-4": { + "PDepend\\": "src/main/php/PDepend" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "description": "Official version of pdepend to be handled with Composer", + "keywords": [ + "PHP Depend", + "PHP_Depend", + "dev", + "pdepend" + ], + "support": { + "issues": "https://github.com/pdepend/pdepend/issues", + "source": "https://github.com/pdepend/pdepend/tree/2.16.2" }, - "time": "2020-12-20T10:01:03+00:00" + "funding": [ + { + "url": "https://tidelift.com/funding/github/packagist/pdepend/pdepend", + "type": "tidelift" + } + ], + "time": "2023-12-17T18:09:59+00:00" }, { "name": "phar-io/manifest", - "version": "2.0.1", + "version": "2.0.4", "source": { "type": "git", "url": "https://github.com/phar-io/manifest.git", - "reference": "85265efd3af7ba3ca4b2a2c34dbfc5788dd29133" + "reference": "54750ef60c58e43759730615a392c31c80e23176" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phar-io/manifest/zipball/85265efd3af7ba3ca4b2a2c34dbfc5788dd29133", - "reference": "85265efd3af7ba3ca4b2a2c34dbfc5788dd29133", + "url": "https://api.github.com/repos/phar-io/manifest/zipball/54750ef60c58e43759730615a392c31c80e23176", + "reference": "54750ef60c58e43759730615a392c31c80e23176", "shasum": "" }, "require": { "ext-dom": "*", + "ext-libxml": "*", "ext-phar": "*", "ext-xmlwriter": "*", "phar-io/version": "^3.0.1", @@ -440,22 +902,28 @@ "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/master" + "source": "https://github.com/phar-io/manifest/tree/2.0.4" }, - "time": "2020-06-27T14:33:11+00:00" + "funding": [ + { + "url": "https://github.com/theseer", + "type": "github" + } + ], + "time": "2024-03-03T12:33:53+00:00" }, { "name": "phar-io/version", - "version": "3.1.0", + "version": "3.2.1", "source": { "type": "git", "url": "https://github.com/phar-io/version.git", - "reference": "bae7c545bef187884426f042434e561ab1ddb182" + "reference": "4f7fd7836c6f332bb2933569e566a0d6c4cbed74" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phar-io/version/zipball/bae7c545bef187884426f042434e561ab1ddb182", - "reference": "bae7c545bef187884426f042434e561ab1ddb182", + "url": "https://api.github.com/repos/phar-io/version/zipball/4f7fd7836c6f332bb2933569e566a0d6c4cbed74", + "reference": "4f7fd7836c6f332bb2933569e566a0d6c4cbed74", "shasum": "" }, "require": { @@ -491,251 +959,109 @@ "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.1.0" - }, - "time": "2021-02-23T14:00:09+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" + "source": "https://github.com/phar-io/version/tree/3.2.1" }, - "time": "2020-06-27T09:03:43+00:00" + "time": "2022-02-21T01:04:05+00:00" }, { - "name": "phpdocumentor/reflection-docblock", - "version": "5.2.2", + "name": "phpmd/phpmd", + "version": "2.15.0", "source": { "type": "git", - "url": "https://github.com/phpDocumentor/ReflectionDocBlock.git", - "reference": "069a785b2141f5bcf49f3e353548dc1cce6df556" + "url": "https://github.com/phpmd/phpmd.git", + "reference": "74a1f56e33afad4128b886e334093e98e1b5e7c0" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/069a785b2141f5bcf49f3e353548dc1cce6df556", - "reference": "069a785b2141f5bcf49f3e353548dc1cce6df556", + "url": "https://api.github.com/repos/phpmd/phpmd/zipball/74a1f56e33afad4128b886e334093e98e1b5e7c0", + "reference": "74a1f56e33afad4128b886e334093e98e1b5e7c0", "shasum": "" }, "require": { - "ext-filter": "*", - "php": "^7.2 || ^8.0", - "phpdocumentor/reflection-common": "^2.2", - "phpdocumentor/type-resolver": "^1.3", - "webmozart/assert": "^1.9.1" + "composer/xdebug-handler": "^1.0 || ^2.0 || ^3.0", + "ext-xml": "*", + "pdepend/pdepend": "^2.16.1", + "php": ">=5.3.9" }, "require-dev": { - "mockery/mockery": "~1.3.2" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "5.x-dev" - } - }, - "autoload": { - "psr-4": { - "phpDocumentor\\Reflection\\": "src" - } + "easy-doc/easy-doc": "0.0.0 || ^1.3.2", + "ext-json": "*", + "ext-simplexml": "*", + "gregwar/rst": "^1.0", + "mikey179/vfsstream": "^1.6.8", + "squizlabs/php_codesniffer": "^2.9.2 || ^3.7.2" }, - "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" - } + "bin": [ + "src/bin/phpmd" ], - "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/master" - }, - "time": "2020-09-03T19:13:55+00:00" - }, - { - "name": "phpdocumentor/type-resolver", - "version": "1.4.0", - "source": { - "type": "git", - "url": "https://github.com/phpDocumentor/TypeResolver.git", - "reference": "6a467b8989322d92aa1c8bf2bebcc6e5c2ba55c0" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/phpDocumentor/TypeResolver/zipball/6a467b8989322d92aa1c8bf2bebcc6e5c2ba55c0", - "reference": "6a467b8989322d92aa1c8bf2bebcc6e5c2ba55c0", - "shasum": "" - }, - "require": { - "php": "^7.2 || ^8.0", - "phpdocumentor/reflection-common": "^2.0" - }, - "require-dev": { - "ext-tokenizer": "*" - }, "type": "library", - "extra": { - "branch-alias": { - "dev-1.x": "1.x-dev" - } - }, "autoload": { - "psr-4": { - "phpDocumentor\\Reflection\\": "src" + "psr-0": { + "PHPMD\\": "src/main/php" } }, "notification-url": "https://packagist.org/downloads/", "license": [ - "MIT" + "BSD-3-Clause" ], "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.4.0" - }, - "time": "2020-09-17T18:55:26+00:00" - }, - { - "name": "phpspec/prophecy", - "version": "1.13.0", - "source": { - "type": "git", - "url": "https://github.com/phpspec/prophecy.git", - "reference": "be1996ed8adc35c3fd795488a653f4b518be70ea" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/phpspec/prophecy/zipball/be1996ed8adc35c3fd795488a653f4b518be70ea", - "reference": "be1996ed8adc35c3fd795488a653f4b518be70ea", - "shasum": "" - }, - "require": { - "doctrine/instantiator": "^1.2", - "php": "^7.2 || ~8.0, <8.1", - "phpdocumentor/reflection-docblock": "^5.2", - "sebastian/comparator": "^3.0 || ^4.0", - "sebastian/recursion-context": "^3.0 || ^4.0" - }, - "require-dev": { - "phpspec/phpspec": "^6.0", - "phpunit/phpunit": "^8.0 || ^9.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.11.x-dev" - } - }, - "autoload": { - "psr-4": { - "Prophecy\\": "src/Prophecy" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ + "name": "Manuel Pichler", + "email": "github@manuel-pichler.de", + "homepage": "https://github.com/manuelpichler", + "role": "Project Founder" + }, { - "name": "Konstantin Kudryashov", - "email": "ever.zet@gmail.com", - "homepage": "http://everzet.com/" + "name": "Marc Würth", + "email": "ravage@bluewin.ch", + "homepage": "https://github.com/ravage84", + "role": "Project Maintainer" }, { - "name": "Marcello Duarte", - "email": "marcello.duarte@gmail.com" + "name": "Other contributors", + "homepage": "https://github.com/phpmd/phpmd/graphs/contributors", + "role": "Contributors" } ], - "description": "Highly opinionated mocking framework for PHP 5.3+", - "homepage": "https://github.com/phpspec/prophecy", + "description": "PHPMD is a spin-off project of PHP Depend and aims to be a PHP equivalent of the well known Java tool PMD.", + "homepage": "https://phpmd.org/", "keywords": [ - "Double", - "Dummy", - "fake", - "mock", - "spy", - "stub" + "dev", + "mess detection", + "mess detector", + "pdepend", + "phpmd", + "pmd" ], "support": { - "issues": "https://github.com/phpspec/prophecy/issues", - "source": "https://github.com/phpspec/prophecy/tree/1.13.0" + "irc": "irc://irc.freenode.org/phpmd", + "issues": "https://github.com/phpmd/phpmd/issues", + "source": "https://github.com/phpmd/phpmd/tree/2.15.0" }, - "time": "2021-03-17T13:42:18+00:00" + "funding": [ + { + "url": "https://tidelift.com/funding/github/packagist/phpmd/phpmd", + "type": "tidelift" + } + ], + "time": "2023-12-11T08:22:20+00:00" }, { "name": "phpstan/phpstan", - "version": "0.12.83", + "version": "1.12.25", "source": { "type": "git", "url": "https://github.com/phpstan/phpstan.git", - "reference": "4a967cec6efb46b500dd6d768657336a3ffe699f" + "reference": "e310849a19e02b8bfcbb63147f495d8f872dd96f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpstan/phpstan/zipball/4a967cec6efb46b500dd6d768657336a3ffe699f", - "reference": "4a967cec6efb46b500dd6d768657336a3ffe699f", + "url": "https://api.github.com/repos/phpstan/phpstan/zipball/e310849a19e02b8bfcbb63147f495d8f872dd96f", + "reference": "e310849a19e02b8bfcbb63147f495d8f872dd96f", "shasum": "" }, "require": { - "php": "^7.1|^8.0" + "php": "^7.2|^8.0" }, "conflict": { "phpstan/phpstan-shim": "*" @@ -745,11 +1071,6 @@ "phpstan.phar" ], "type": "library", - "extra": { - "branch-alias": { - "dev-master": "0.12-dev" - } - }, "autoload": { "files": [ "bootstrap.php" @@ -760,9 +1081,16 @@ "MIT" ], "description": "PHPStan - PHP Static Analysis Tool", + "keywords": [ + "dev", + "static analysis" + ], "support": { + "docs": "https://phpstan.org/user-guide/getting-started", + "forum": "https://github.com/phpstan/phpstan/discussions", "issues": "https://github.com/phpstan/phpstan/issues", - "source": "https://github.com/phpstan/phpstan/tree/0.12.83" + "security": "https://github.com/phpstan/phpstan/security/policy", + "source": "https://github.com/phpstan/phpstan-src" }, "funding": [ { @@ -770,56 +1098,52 @@ "type": "github" }, { - "url": "https://www.patreon.com/phpstan", - "type": "patreon" - }, - { - "url": "https://tidelift.com/funding/github/packagist/phpstan/phpstan", - "type": "tidelift" + "url": "https://github.com/phpstan", + "type": "github" } ], - "time": "2021-04-03T15:35:45+00:00" + "time": "2025-04-27T12:20:45+00:00" }, { "name": "phpunit/php-code-coverage", - "version": "9.2.6", + "version": "10.1.16", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-code-coverage.git", - "reference": "f6293e1b30a2354e8428e004689671b83871edde" + "reference": "7e308268858ed6baedc8704a304727d20bc07c77" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/f6293e1b30a2354e8428e004689671b83871edde", - "reference": "f6293e1b30a2354e8428e004689671b83871edde", + "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/7e308268858ed6baedc8704a304727d20bc07c77", + "reference": "7e308268858ed6baedc8704a304727d20bc07c77", "shasum": "" }, "require": { "ext-dom": "*", "ext-libxml": "*", "ext-xmlwriter": "*", - "nikic/php-parser": "^4.10.2", - "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" + "nikic/php-parser": "^4.19.1 || ^5.1.0", + "php": ">=8.1", + "phpunit/php-file-iterator": "^4.1.0", + "phpunit/php-text-template": "^3.0.1", + "sebastian/code-unit-reverse-lookup": "^3.0.0", + "sebastian/complexity": "^3.2.0", + "sebastian/environment": "^6.1.0", + "sebastian/lines-of-code": "^2.0.2", + "sebastian/version": "^4.0.1", + "theseer/tokenizer": "^1.2.3" }, "require-dev": { - "phpunit/phpunit": "^9.3" + "phpunit/phpunit": "^10.1" }, "suggest": { - "ext-pcov": "*", - "ext-xdebug": "*" + "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" + "dev-main": "10.1.x-dev" } }, "autoload": { @@ -847,7 +1171,8 @@ ], "support": { "issues": "https://github.com/sebastianbergmann/php-code-coverage/issues", - "source": "https://github.com/sebastianbergmann/php-code-coverage/tree/9.2.6" + "security": "https://github.com/sebastianbergmann/php-code-coverage/security/policy", + "source": "https://github.com/sebastianbergmann/php-code-coverage/tree/10.1.16" }, "funding": [ { @@ -855,32 +1180,32 @@ "type": "github" } ], - "time": "2021-03-28T07:26:59+00:00" + "time": "2024-08-22T04:31:57+00:00" }, { "name": "phpunit/php-file-iterator", - "version": "3.0.5", + "version": "4.1.0", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-file-iterator.git", - "reference": "aa4be8575f26070b100fccb67faabb28f21f66f8" + "reference": "a95037b6d9e608ba092da1b23931e537cadc3c3c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/aa4be8575f26070b100fccb67faabb28f21f66f8", - "reference": "aa4be8575f26070b100fccb67faabb28f21f66f8", + "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/a95037b6d9e608ba092da1b23931e537cadc3c3c", + "reference": "a95037b6d9e608ba092da1b23931e537cadc3c3c", "shasum": "" }, "require": { - "php": ">=7.3" + "php": ">=8.1" }, "require-dev": { - "phpunit/phpunit": "^9.3" + "phpunit/phpunit": "^10.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "3.0-dev" + "dev-main": "4.0-dev" } }, "autoload": { @@ -907,7 +1232,8 @@ ], "support": { "issues": "https://github.com/sebastianbergmann/php-file-iterator/issues", - "source": "https://github.com/sebastianbergmann/php-file-iterator/tree/3.0.5" + "security": "https://github.com/sebastianbergmann/php-file-iterator/security/policy", + "source": "https://github.com/sebastianbergmann/php-file-iterator/tree/4.1.0" }, "funding": [ { @@ -915,28 +1241,28 @@ "type": "github" } ], - "time": "2020-09-28T05:57:25+00:00" + "time": "2023-08-31T06:24:48+00:00" }, { "name": "phpunit/php-invoker", - "version": "3.1.1", + "version": "4.0.0", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-invoker.git", - "reference": "5a10147d0aaf65b58940a0b72f71c9ac0423cc67" + "reference": "f5e568ba02fa5ba0ddd0f618391d5a9ea50b06d7" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-invoker/zipball/5a10147d0aaf65b58940a0b72f71c9ac0423cc67", - "reference": "5a10147d0aaf65b58940a0b72f71c9ac0423cc67", + "url": "https://api.github.com/repos/sebastianbergmann/php-invoker/zipball/f5e568ba02fa5ba0ddd0f618391d5a9ea50b06d7", + "reference": "f5e568ba02fa5ba0ddd0f618391d5a9ea50b06d7", "shasum": "" }, "require": { - "php": ">=7.3" + "php": ">=8.1" }, "require-dev": { "ext-pcntl": "*", - "phpunit/phpunit": "^9.3" + "phpunit/phpunit": "^10.0" }, "suggest": { "ext-pcntl": "*" @@ -944,7 +1270,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "3.1-dev" + "dev-main": "4.0-dev" } }, "autoload": { @@ -970,7 +1296,7 @@ ], "support": { "issues": "https://github.com/sebastianbergmann/php-invoker/issues", - "source": "https://github.com/sebastianbergmann/php-invoker/tree/3.1.1" + "source": "https://github.com/sebastianbergmann/php-invoker/tree/4.0.0" }, "funding": [ { @@ -978,32 +1304,32 @@ "type": "github" } ], - "time": "2020-09-28T05:58:55+00:00" + "time": "2023-02-03T06:56:09+00:00" }, { "name": "phpunit/php-text-template", - "version": "2.0.4", + "version": "3.0.1", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-text-template.git", - "reference": "5da5f67fc95621df9ff4c4e5a84d6a8a2acf7c28" + "reference": "0c7b06ff49e3d5072f057eb1fa59258bf287a748" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-text-template/zipball/5da5f67fc95621df9ff4c4e5a84d6a8a2acf7c28", - "reference": "5da5f67fc95621df9ff4c4e5a84d6a8a2acf7c28", + "url": "https://api.github.com/repos/sebastianbergmann/php-text-template/zipball/0c7b06ff49e3d5072f057eb1fa59258bf287a748", + "reference": "0c7b06ff49e3d5072f057eb1fa59258bf287a748", "shasum": "" }, "require": { - "php": ">=7.3" + "php": ">=8.1" }, "require-dev": { - "phpunit/phpunit": "^9.3" + "phpunit/phpunit": "^10.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "2.0-dev" + "dev-main": "3.0-dev" } }, "autoload": { @@ -1029,7 +1355,8 @@ ], "support": { "issues": "https://github.com/sebastianbergmann/php-text-template/issues", - "source": "https://github.com/sebastianbergmann/php-text-template/tree/2.0.4" + "security": "https://github.com/sebastianbergmann/php-text-template/security/policy", + "source": "https://github.com/sebastianbergmann/php-text-template/tree/3.0.1" }, "funding": [ { @@ -1037,32 +1364,32 @@ "type": "github" } ], - "time": "2020-10-26T05:33:50+00:00" + "time": "2023-08-31T14:07:24+00:00" }, { "name": "phpunit/php-timer", - "version": "5.0.3", + "version": "6.0.0", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-timer.git", - "reference": "5a63ce20ed1b5bf577850e2c4e87f4aa902afbd2" + "reference": "e2a2d67966e740530f4a3343fe2e030ffdc1161d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/5a63ce20ed1b5bf577850e2c4e87f4aa902afbd2", - "reference": "5a63ce20ed1b5bf577850e2c4e87f4aa902afbd2", + "url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/e2a2d67966e740530f4a3343fe2e030ffdc1161d", + "reference": "e2a2d67966e740530f4a3343fe2e030ffdc1161d", "shasum": "" }, "require": { - "php": ">=7.3" + "php": ">=8.1" }, "require-dev": { - "phpunit/phpunit": "^9.3" + "phpunit/phpunit": "^10.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "5.0-dev" + "dev-main": "6.0-dev" } }, "autoload": { @@ -1088,7 +1415,7 @@ ], "support": { "issues": "https://github.com/sebastianbergmann/php-timer/issues", - "source": "https://github.com/sebastianbergmann/php-timer/tree/5.0.3" + "source": "https://github.com/sebastianbergmann/php-timer/tree/6.0.0" }, "funding": [ { @@ -1096,59 +1423,52 @@ "type": "github" } ], - "time": "2020-10-26T13:16:10+00:00" + "time": "2023-02-03T06:57:52+00:00" }, { "name": "phpunit/phpunit", - "version": "9.5.4", + "version": "10.5.46", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/phpunit.git", - "reference": "c73c6737305e779771147af66c96ca6a7ed8a741" + "reference": "8080be387a5be380dda48c6f41cee4a13aadab3d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/c73c6737305e779771147af66c96ca6a7ed8a741", - "reference": "c73c6737305e779771147af66c96ca6a7ed8a741", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/8080be387a5be380dda48c6f41cee4a13aadab3d", + "reference": "8080be387a5be380dda48c6f41cee4a13aadab3d", "shasum": "" }, "require": { - "doctrine/instantiator": "^1.3.1", "ext-dom": "*", "ext-json": "*", "ext-libxml": "*", "ext-mbstring": "*", "ext-xml": "*", "ext-xmlwriter": "*", - "myclabs/deep-copy": "^1.10.1", - "phar-io/manifest": "^2.0.1", - "phar-io/version": "^3.0.2", - "php": ">=7.3", - "phpspec/prophecy": "^1.12.1", - "phpunit/php-code-coverage": "^9.2.3", - "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.5", - "sebastian/diff": "^4.0.3", - "sebastian/environment": "^5.1.3", - "sebastian/exporter": "^4.0.3", - "sebastian/global-state": "^5.0.1", - "sebastian/object-enumerator": "^4.0.3", - "sebastian/resource-operations": "^3.0.3", - "sebastian/type": "^2.3", - "sebastian/version": "^3.0.2" - }, - "require-dev": { - "ext-pdo": "*", - "phpspec/prophecy-phpunit": "^2.0.1" + "myclabs/deep-copy": "^1.13.1", + "phar-io/manifest": "^2.0.4", + "phar-io/version": "^3.2.1", + "php": ">=8.1", + "phpunit/php-code-coverage": "^10.1.16", + "phpunit/php-file-iterator": "^4.1.0", + "phpunit/php-invoker": "^4.0.0", + "phpunit/php-text-template": "^3.0.1", + "phpunit/php-timer": "^6.0.0", + "sebastian/cli-parser": "^2.0.1", + "sebastian/code-unit": "^2.0.0", + "sebastian/comparator": "^5.0.3", + "sebastian/diff": "^5.1.1", + "sebastian/environment": "^6.1.0", + "sebastian/exporter": "^5.1.2", + "sebastian/global-state": "^6.0.2", + "sebastian/object-enumerator": "^5.0.0", + "sebastian/recursion-context": "^5.0.0", + "sebastian/type": "^4.0.0", + "sebastian/version": "^4.0.1" }, "suggest": { - "ext-soap": "*", - "ext-xdebug": "*" + "ext-soap": "To be able to generate mocks based on WSDL files" }, "bin": [ "phpunit" @@ -1156,15 +1476,15 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "9.5-dev" + "dev-main": "10.5-dev" } }, "autoload": { - "classmap": [ - "src/" - ], "files": [ "src/Framework/Assert/Functions.php" + ], + "classmap": [ + "src/" ] }, "notification-url": "https://packagist.org/downloads/", @@ -1187,54 +1507,170 @@ ], "support": { "issues": "https://github.com/sebastianbergmann/phpunit/issues", - "source": "https://github.com/sebastianbergmann/phpunit/tree/9.5.4" + "security": "https://github.com/sebastianbergmann/phpunit/security/policy", + "source": "https://github.com/sebastianbergmann/phpunit/tree/10.5.46" }, "funding": [ { - "url": "https://phpunit.de/donate.html", + "url": "https://phpunit.de/sponsors.html", "type": "custom" }, { "url": "https://github.com/sebastianbergmann", "type": "github" + }, + { + "url": "https://liberapay.com/sebastianbergmann", + "type": "liberapay" + }, + { + "url": "https://thanks.dev/u/gh/sebastianbergmann", + "type": "thanks_dev" + }, + { + "url": "https://tidelift.com/funding/github/packagist/phpunit/phpunit", + "type": "tidelift" } ], - "time": "2021-03-23T07:16:29+00:00" + "time": "2025-05-02T06:46:24+00:00" }, { - "name": "sebastian/cli-parser", - "version": "1.0.1", + "name": "psr/container", + "version": "2.0.2", "source": { "type": "git", - "url": "https://github.com/sebastianbergmann/cli-parser.git", - "reference": "442e7c7e687e42adc03470c7b668bc4b2402c0b2" + "url": "https://github.com/php-fig/container.git", + "reference": "c71ecc56dfe541dbd90c5360474fbc405f8d5963" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/cli-parser/zipball/442e7c7e687e42adc03470c7b668bc4b2402c0b2", - "reference": "442e7c7e687e42adc03470c7b668bc4b2402c0b2", + "url": "https://api.github.com/repos/php-fig/container/zipball/c71ecc56dfe541dbd90c5360474fbc405f8d5963", + "reference": "c71ecc56dfe541dbd90c5360474fbc405f8d5963", "shasum": "" }, "require": { - "php": ">=7.3" - }, - "require-dev": { - "phpunit/phpunit": "^9.3" + "php": ">=7.4.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.0-dev" + "dev-master": "2.0.x-dev" } }, "autoload": { - "classmap": [ - "src/" - ] + "psr-4": { + "Psr\\Container\\": "src/" + } }, "notification-url": "https://packagist.org/downloads/", "license": [ - "BSD-3-Clause" + "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/2.0.2" + }, + "time": "2021-11-05T16:47:00+00:00" + }, + { + "name": "psr/log", + "version": "3.0.2", + "source": { + "type": "git", + "url": "https://github.com/php-fig/log.git", + "reference": "f16e1d5863e37f8d8c2a01719f5b34baa2b714d3" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/log/zipball/f16e1d5863e37f8d8c2a01719f5b34baa2b714d3", + "reference": "f16e1d5863e37f8d8c2a01719f5b34baa2b714d3", + "shasum": "" + }, + "require": { + "php": ">=8.0.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\Log\\": "src" + } + }, + "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/3.0.2" + }, + "time": "2024-09-11T13:17:53+00:00" + }, + { + "name": "sebastian/cli-parser", + "version": "2.0.1", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/cli-parser.git", + "reference": "c34583b87e7b7a8055bf6c450c2c77ce32a24084" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/cli-parser/zipball/c34583b87e7b7a8055bf6c450c2c77ce32a24084", + "reference": "c34583b87e7b7a8055bf6c450c2c77ce32a24084", + "shasum": "" + }, + "require": { + "php": ">=8.1" + }, + "require-dev": { + "phpunit/phpunit": "^10.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "2.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" ], "authors": [ { @@ -1247,7 +1683,8 @@ "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" + "security": "https://github.com/sebastianbergmann/cli-parser/security/policy", + "source": "https://github.com/sebastianbergmann/cli-parser/tree/2.0.1" }, "funding": [ { @@ -1255,32 +1692,32 @@ "type": "github" } ], - "time": "2020-09-28T06:08:49+00:00" + "time": "2024-03-02T07:12:49+00:00" }, { "name": "sebastian/code-unit", - "version": "1.0.8", + "version": "2.0.0", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/code-unit.git", - "reference": "1fc9f64c0927627ef78ba436c9b17d967e68e120" + "reference": "a81fee9eef0b7a76af11d121767abc44c104e503" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/code-unit/zipball/1fc9f64c0927627ef78ba436c9b17d967e68e120", - "reference": "1fc9f64c0927627ef78ba436c9b17d967e68e120", + "url": "https://api.github.com/repos/sebastianbergmann/code-unit/zipball/a81fee9eef0b7a76af11d121767abc44c104e503", + "reference": "a81fee9eef0b7a76af11d121767abc44c104e503", "shasum": "" }, "require": { - "php": ">=7.3" + "php": ">=8.1" }, "require-dev": { - "phpunit/phpunit": "^9.3" + "phpunit/phpunit": "^10.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.0-dev" + "dev-main": "2.0-dev" } }, "autoload": { @@ -1303,7 +1740,7 @@ "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" + "source": "https://github.com/sebastianbergmann/code-unit/tree/2.0.0" }, "funding": [ { @@ -1311,32 +1748,32 @@ "type": "github" } ], - "time": "2020-10-26T13:08:54+00:00" + "time": "2023-02-03T06:58:43+00:00" }, { "name": "sebastian/code-unit-reverse-lookup", - "version": "2.0.3", + "version": "3.0.0", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/code-unit-reverse-lookup.git", - "reference": "ac91f01ccec49fb77bdc6fd1e548bc70f7faa3e5" + "reference": "5e3a687f7d8ae33fb362c5c0743794bbb2420a1d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/code-unit-reverse-lookup/zipball/ac91f01ccec49fb77bdc6fd1e548bc70f7faa3e5", - "reference": "ac91f01ccec49fb77bdc6fd1e548bc70f7faa3e5", + "url": "https://api.github.com/repos/sebastianbergmann/code-unit-reverse-lookup/zipball/5e3a687f7d8ae33fb362c5c0743794bbb2420a1d", + "reference": "5e3a687f7d8ae33fb362c5c0743794bbb2420a1d", "shasum": "" }, "require": { - "php": ">=7.3" + "php": ">=8.1" }, "require-dev": { - "phpunit/phpunit": "^9.3" + "phpunit/phpunit": "^10.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "2.0-dev" + "dev-main": "3.0-dev" } }, "autoload": { @@ -1358,7 +1795,7 @@ "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" + "source": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/tree/3.0.0" }, "funding": [ { @@ -1366,34 +1803,36 @@ "type": "github" } ], - "time": "2020-09-28T05:30:19+00:00" + "time": "2023-02-03T06:59:15+00:00" }, { "name": "sebastian/comparator", - "version": "4.0.6", + "version": "5.0.3", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/comparator.git", - "reference": "55f4261989e546dc112258c7a75935a81a7ce382" + "reference": "a18251eb0b7a2dcd2f7aa3d6078b18545ef0558e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/55f4261989e546dc112258c7a75935a81a7ce382", - "reference": "55f4261989e546dc112258c7a75935a81a7ce382", + "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/a18251eb0b7a2dcd2f7aa3d6078b18545ef0558e", + "reference": "a18251eb0b7a2dcd2f7aa3d6078b18545ef0558e", "shasum": "" }, "require": { - "php": ">=7.3", - "sebastian/diff": "^4.0", - "sebastian/exporter": "^4.0" + "ext-dom": "*", + "ext-mbstring": "*", + "php": ">=8.1", + "sebastian/diff": "^5.0", + "sebastian/exporter": "^5.0" }, "require-dev": { - "phpunit/phpunit": "^9.3" + "phpunit/phpunit": "^10.5" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "4.0-dev" + "dev-main": "5.0-dev" } }, "autoload": { @@ -1432,7 +1871,8 @@ ], "support": { "issues": "https://github.com/sebastianbergmann/comparator/issues", - "source": "https://github.com/sebastianbergmann/comparator/tree/4.0.6" + "security": "https://github.com/sebastianbergmann/comparator/security/policy", + "source": "https://github.com/sebastianbergmann/comparator/tree/5.0.3" }, "funding": [ { @@ -1440,33 +1880,33 @@ "type": "github" } ], - "time": "2020-10-26T15:49:45+00:00" + "time": "2024-10-18T14:56:07+00:00" }, { "name": "sebastian/complexity", - "version": "2.0.2", + "version": "3.2.0", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/complexity.git", - "reference": "739b35e53379900cc9ac327b2147867b8b6efd88" + "reference": "68ff824baeae169ec9f2137158ee529584553799" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/complexity/zipball/739b35e53379900cc9ac327b2147867b8b6efd88", - "reference": "739b35e53379900cc9ac327b2147867b8b6efd88", + "url": "https://api.github.com/repos/sebastianbergmann/complexity/zipball/68ff824baeae169ec9f2137158ee529584553799", + "reference": "68ff824baeae169ec9f2137158ee529584553799", "shasum": "" }, "require": { - "nikic/php-parser": "^4.7", - "php": ">=7.3" + "nikic/php-parser": "^4.18 || ^5.0", + "php": ">=8.1" }, "require-dev": { - "phpunit/phpunit": "^9.3" + "phpunit/phpunit": "^10.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "2.0-dev" + "dev-main": "3.2-dev" } }, "autoload": { @@ -1489,7 +1929,8 @@ "homepage": "https://github.com/sebastianbergmann/complexity", "support": { "issues": "https://github.com/sebastianbergmann/complexity/issues", - "source": "https://github.com/sebastianbergmann/complexity/tree/2.0.2" + "security": "https://github.com/sebastianbergmann/complexity/security/policy", + "source": "https://github.com/sebastianbergmann/complexity/tree/3.2.0" }, "funding": [ { @@ -1497,33 +1938,33 @@ "type": "github" } ], - "time": "2020-10-26T15:52:27+00:00" + "time": "2023-12-21T08:37:17+00:00" }, { "name": "sebastian/diff", - "version": "4.0.4", + "version": "5.1.1", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/diff.git", - "reference": "3461e3fccc7cfdfc2720be910d3bd73c69be590d" + "reference": "c41e007b4b62af48218231d6c2275e4c9b975b2e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/3461e3fccc7cfdfc2720be910d3bd73c69be590d", - "reference": "3461e3fccc7cfdfc2720be910d3bd73c69be590d", + "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/c41e007b4b62af48218231d6c2275e4c9b975b2e", + "reference": "c41e007b4b62af48218231d6c2275e4c9b975b2e", "shasum": "" }, "require": { - "php": ">=7.3" + "php": ">=8.1" }, "require-dev": { - "phpunit/phpunit": "^9.3", - "symfony/process": "^4.2 || ^5" + "phpunit/phpunit": "^10.0", + "symfony/process": "^6.4" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "4.0-dev" + "dev-main": "5.1-dev" } }, "autoload": { @@ -1555,7 +1996,8 @@ ], "support": { "issues": "https://github.com/sebastianbergmann/diff/issues", - "source": "https://github.com/sebastianbergmann/diff/tree/4.0.4" + "security": "https://github.com/sebastianbergmann/diff/security/policy", + "source": "https://github.com/sebastianbergmann/diff/tree/5.1.1" }, "funding": [ { @@ -1563,27 +2005,27 @@ "type": "github" } ], - "time": "2020-10-26T13:10:38+00:00" + "time": "2024-03-02T07:15:17+00:00" }, { "name": "sebastian/environment", - "version": "5.1.3", + "version": "6.1.0", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/environment.git", - "reference": "388b6ced16caa751030f6a69e588299fa09200ac" + "reference": "8074dbcd93529b357029f5cc5058fd3e43666984" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/388b6ced16caa751030f6a69e588299fa09200ac", - "reference": "388b6ced16caa751030f6a69e588299fa09200ac", + "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/8074dbcd93529b357029f5cc5058fd3e43666984", + "reference": "8074dbcd93529b357029f5cc5058fd3e43666984", "shasum": "" }, "require": { - "php": ">=7.3" + "php": ">=8.1" }, "require-dev": { - "phpunit/phpunit": "^9.3" + "phpunit/phpunit": "^10.0" }, "suggest": { "ext-posix": "*" @@ -1591,7 +2033,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "5.1-dev" + "dev-main": "6.1-dev" } }, "autoload": { @@ -1610,7 +2052,7 @@ } ], "description": "Provides functionality to handle HHVM/PHP environments", - "homepage": "http://www.github.com/sebastianbergmann/environment", + "homepage": "https://github.com/sebastianbergmann/environment", "keywords": [ "Xdebug", "environment", @@ -1618,7 +2060,8 @@ ], "support": { "issues": "https://github.com/sebastianbergmann/environment/issues", - "source": "https://github.com/sebastianbergmann/environment/tree/5.1.3" + "security": "https://github.com/sebastianbergmann/environment/security/policy", + "source": "https://github.com/sebastianbergmann/environment/tree/6.1.0" }, "funding": [ { @@ -1626,34 +2069,34 @@ "type": "github" } ], - "time": "2020-09-28T05:52:38+00:00" + "time": "2024-03-23T08:47:14+00:00" }, { "name": "sebastian/exporter", - "version": "4.0.3", + "version": "5.1.2", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/exporter.git", - "reference": "d89cc98761b8cb5a1a235a6b703ae50d34080e65" + "reference": "955288482d97c19a372d3f31006ab3f37da47adf" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/d89cc98761b8cb5a1a235a6b703ae50d34080e65", - "reference": "d89cc98761b8cb5a1a235a6b703ae50d34080e65", + "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/955288482d97c19a372d3f31006ab3f37da47adf", + "reference": "955288482d97c19a372d3f31006ab3f37da47adf", "shasum": "" }, "require": { - "php": ">=7.3", - "sebastian/recursion-context": "^4.0" + "ext-mbstring": "*", + "php": ">=8.1", + "sebastian/recursion-context": "^5.0" }, "require-dev": { - "ext-mbstring": "*", - "phpunit/phpunit": "^9.3" + "phpunit/phpunit": "^10.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "4.0-dev" + "dev-main": "5.1-dev" } }, "autoload": { @@ -1688,14 +2131,15 @@ } ], "description": "Provides the functionality to export PHP variables for visualization", - "homepage": "http://www.github.com/sebastianbergmann/exporter", + "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.3" + "security": "https://github.com/sebastianbergmann/exporter/security/policy", + "source": "https://github.com/sebastianbergmann/exporter/tree/5.1.2" }, "funding": [ { @@ -1703,38 +2147,35 @@ "type": "github" } ], - "time": "2020-09-28T05:24:23+00:00" + "time": "2024-03-02T07:17:12+00:00" }, { "name": "sebastian/global-state", - "version": "5.0.2", + "version": "6.0.2", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/global-state.git", - "reference": "a90ccbddffa067b51f574dea6eb25d5680839455" + "reference": "987bafff24ecc4c9ac418cab1145b96dd6e9cbd9" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/a90ccbddffa067b51f574dea6eb25d5680839455", - "reference": "a90ccbddffa067b51f574dea6eb25d5680839455", + "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/987bafff24ecc4c9ac418cab1145b96dd6e9cbd9", + "reference": "987bafff24ecc4c9ac418cab1145b96dd6e9cbd9", "shasum": "" }, "require": { - "php": ">=7.3", - "sebastian/object-reflector": "^2.0", - "sebastian/recursion-context": "^4.0" + "php": ">=8.1", + "sebastian/object-reflector": "^3.0", + "sebastian/recursion-context": "^5.0" }, "require-dev": { "ext-dom": "*", - "phpunit/phpunit": "^9.3" - }, - "suggest": { - "ext-uopz": "*" + "phpunit/phpunit": "^10.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "5.0-dev" + "dev-main": "6.0-dev" } }, "autoload": { @@ -1753,13 +2194,14 @@ } ], "description": "Snapshotting of global state", - "homepage": "http://www.github.com/sebastianbergmann/global-state", + "homepage": "https://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.2" + "security": "https://github.com/sebastianbergmann/global-state/security/policy", + "source": "https://github.com/sebastianbergmann/global-state/tree/6.0.2" }, "funding": [ { @@ -1767,33 +2209,33 @@ "type": "github" } ], - "time": "2020-10-26T15:55:19+00:00" + "time": "2024-03-02T07:19:19+00:00" }, { "name": "sebastian/lines-of-code", - "version": "1.0.3", + "version": "2.0.2", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/lines-of-code.git", - "reference": "c1c2e997aa3146983ed888ad08b15470a2e22ecc" + "reference": "856e7f6a75a84e339195d48c556f23be2ebf75d0" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/lines-of-code/zipball/c1c2e997aa3146983ed888ad08b15470a2e22ecc", - "reference": "c1c2e997aa3146983ed888ad08b15470a2e22ecc", + "url": "https://api.github.com/repos/sebastianbergmann/lines-of-code/zipball/856e7f6a75a84e339195d48c556f23be2ebf75d0", + "reference": "856e7f6a75a84e339195d48c556f23be2ebf75d0", "shasum": "" }, "require": { - "nikic/php-parser": "^4.6", - "php": ">=7.3" + "nikic/php-parser": "^4.18 || ^5.0", + "php": ">=8.1" }, "require-dev": { - "phpunit/phpunit": "^9.3" + "phpunit/phpunit": "^10.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.0-dev" + "dev-main": "2.0-dev" } }, "autoload": { @@ -1816,7 +2258,8 @@ "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" + "security": "https://github.com/sebastianbergmann/lines-of-code/security/policy", + "source": "https://github.com/sebastianbergmann/lines-of-code/tree/2.0.2" }, "funding": [ { @@ -1824,34 +2267,34 @@ "type": "github" } ], - "time": "2020-11-28T06:42:11+00:00" + "time": "2023-12-21T08:38:20+00:00" }, { "name": "sebastian/object-enumerator", - "version": "4.0.4", + "version": "5.0.0", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/object-enumerator.git", - "reference": "5c9eeac41b290a3712d88851518825ad78f45c71" + "reference": "202d0e344a580d7f7d04b3fafce6933e59dae906" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/object-enumerator/zipball/5c9eeac41b290a3712d88851518825ad78f45c71", - "reference": "5c9eeac41b290a3712d88851518825ad78f45c71", + "url": "https://api.github.com/repos/sebastianbergmann/object-enumerator/zipball/202d0e344a580d7f7d04b3fafce6933e59dae906", + "reference": "202d0e344a580d7f7d04b3fafce6933e59dae906", "shasum": "" }, "require": { - "php": ">=7.3", - "sebastian/object-reflector": "^2.0", - "sebastian/recursion-context": "^4.0" + "php": ">=8.1", + "sebastian/object-reflector": "^3.0", + "sebastian/recursion-context": "^5.0" }, "require-dev": { - "phpunit/phpunit": "^9.3" + "phpunit/phpunit": "^10.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "4.0-dev" + "dev-main": "5.0-dev" } }, "autoload": { @@ -1873,7 +2316,7 @@ "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" + "source": "https://github.com/sebastianbergmann/object-enumerator/tree/5.0.0" }, "funding": [ { @@ -1881,32 +2324,32 @@ "type": "github" } ], - "time": "2020-10-26T13:12:34+00:00" + "time": "2023-02-03T07:08:32+00:00" }, { "name": "sebastian/object-reflector", - "version": "2.0.4", + "version": "3.0.0", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/object-reflector.git", - "reference": "b4f479ebdbf63ac605d183ece17d8d7fe49c15c7" + "reference": "24ed13d98130f0e7122df55d06c5c4942a577957" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/object-reflector/zipball/b4f479ebdbf63ac605d183ece17d8d7fe49c15c7", - "reference": "b4f479ebdbf63ac605d183ece17d8d7fe49c15c7", + "url": "https://api.github.com/repos/sebastianbergmann/object-reflector/zipball/24ed13d98130f0e7122df55d06c5c4942a577957", + "reference": "24ed13d98130f0e7122df55d06c5c4942a577957", "shasum": "" }, "require": { - "php": ">=7.3" + "php": ">=8.1" }, "require-dev": { - "phpunit/phpunit": "^9.3" + "phpunit/phpunit": "^10.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "2.0-dev" + "dev-main": "3.0-dev" } }, "autoload": { @@ -1928,7 +2371,7 @@ "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" + "source": "https://github.com/sebastianbergmann/object-reflector/tree/3.0.0" }, "funding": [ { @@ -1936,32 +2379,32 @@ "type": "github" } ], - "time": "2020-10-26T13:14:26+00:00" + "time": "2023-02-03T07:06:18+00:00" }, { "name": "sebastian/recursion-context", - "version": "4.0.4", + "version": "5.0.0", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/recursion-context.git", - "reference": "cd9d8cf3c5804de4341c283ed787f099f5506172" + "reference": "05909fb5bc7df4c52992396d0116aed689f93712" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/cd9d8cf3c5804de4341c283ed787f099f5506172", - "reference": "cd9d8cf3c5804de4341c283ed787f099f5506172", + "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/05909fb5bc7df4c52992396d0116aed689f93712", + "reference": "05909fb5bc7df4c52992396d0116aed689f93712", "shasum": "" }, "require": { - "php": ">=7.3" + "php": ">=8.1" }, "require-dev": { - "phpunit/phpunit": "^9.3" + "phpunit/phpunit": "^10.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "4.0-dev" + "dev-main": "5.0-dev" } }, "autoload": { @@ -1988,10 +2431,10 @@ } ], "description": "Provides functionality to recursively process PHP variables", - "homepage": "http://www.github.com/sebastianbergmann/recursion-context", + "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.4" + "source": "https://github.com/sebastianbergmann/recursion-context/tree/5.0.0" }, "funding": [ { @@ -1999,32 +2442,32 @@ "type": "github" } ], - "time": "2020-10-26T13:17:30+00:00" + "time": "2023-02-03T07:05:40+00:00" }, { - "name": "sebastian/resource-operations", - "version": "3.0.3", + "name": "sebastian/type", + "version": "4.0.0", "source": { "type": "git", - "url": "https://github.com/sebastianbergmann/resource-operations.git", - "reference": "0f4443cb3a1d92ce809899753bc0d5d5a8dd19a8" + "url": "https://github.com/sebastianbergmann/type.git", + "reference": "462699a16464c3944eefc02ebdd77882bd3925bf" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/resource-operations/zipball/0f4443cb3a1d92ce809899753bc0d5d5a8dd19a8", - "reference": "0f4443cb3a1d92ce809899753bc0d5d5a8dd19a8", + "url": "https://api.github.com/repos/sebastianbergmann/type/zipball/462699a16464c3944eefc02ebdd77882bd3925bf", + "reference": "462699a16464c3944eefc02ebdd77882bd3925bf", "shasum": "" }, "require": { - "php": ">=7.3" + "php": ">=8.1" }, "require-dev": { - "phpunit/phpunit": "^9.0" + "phpunit/phpunit": "^10.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "3.0-dev" + "dev-main": "4.0-dev" } }, "autoload": { @@ -2039,14 +2482,15 @@ "authors": [ { "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" + "email": "sebastian@phpunit.de", + "role": "lead" } ], - "description": "Provides a list of PHP built-in functions that operate on resources", - "homepage": "https://www.github.com/sebastianbergmann/resource-operations", + "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/resource-operations/issues", - "source": "https://github.com/sebastianbergmann/resource-operations/tree/3.0.3" + "issues": "https://github.com/sebastianbergmann/type/issues", + "source": "https://github.com/sebastianbergmann/type/tree/4.0.0" }, "funding": [ { @@ -2054,32 +2498,29 @@ "type": "github" } ], - "time": "2020-09-28T06:45:17+00:00" + "time": "2023-02-03T07:10:45+00:00" }, { - "name": "sebastian/type", - "version": "2.3.1", + "name": "sebastian/version", + "version": "4.0.1", "source": { "type": "git", - "url": "https://github.com/sebastianbergmann/type.git", - "reference": "81cd61ab7bbf2de744aba0ea61fae32f721df3d2" + "url": "https://github.com/sebastianbergmann/version.git", + "reference": "c51fa83a5d8f43f1402e3f32a005e6262244ef17" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/type/zipball/81cd61ab7bbf2de744aba0ea61fae32f721df3d2", - "reference": "81cd61ab7bbf2de744aba0ea61fae32f721df3d2", + "url": "https://api.github.com/repos/sebastianbergmann/version/zipball/c51fa83a5d8f43f1402e3f32a005e6262244ef17", + "reference": "c51fa83a5d8f43f1402e3f32a005e6262244ef17", "shasum": "" }, "require": { - "php": ">=7.3" - }, - "require-dev": { - "phpunit/phpunit": "^9.3" + "php": ">=8.1" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "2.3-dev" + "dev-main": "4.0-dev" } }, "autoload": { @@ -2098,11 +2539,11 @@ "role": "lead" } ], - "description": "Collection of value objects that represent the types of the PHP type system", - "homepage": "https://github.com/sebastianbergmann/type", + "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/type/issues", - "source": "https://github.com/sebastianbergmann/type/tree/2.3.1" + "issues": "https://github.com/sebastianbergmann/version/issues", + "source": "https://github.com/sebastianbergmann/version/tree/4.0.1" }, "funding": [ { @@ -2110,97 +2551,130 @@ "type": "github" } ], - "time": "2020-10-26T13:18:59+00:00" + "time": "2023-02-07T11:34:05+00:00" }, { - "name": "sebastian/version", - "version": "3.0.2", + "name": "squizlabs/php_codesniffer", + "version": "3.12.2", "source": { "type": "git", - "url": "https://github.com/sebastianbergmann/version.git", - "reference": "c6c1022351a901512170118436c764e473f6de8c" + "url": "https://github.com/PHPCSStandards/PHP_CodeSniffer.git", + "reference": "6d4cf6032d4b718f168c90a96e36c7d0eaacb2aa" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/version/zipball/c6c1022351a901512170118436c764e473f6de8c", - "reference": "c6c1022351a901512170118436c764e473f6de8c", + "url": "https://api.github.com/repos/PHPCSStandards/PHP_CodeSniffer/zipball/6d4cf6032d4b718f168c90a96e36c7d0eaacb2aa", + "reference": "6d4cf6032d4b718f168c90a96e36c7d0eaacb2aa", "shasum": "" }, "require": { - "php": ">=7.3" + "ext-simplexml": "*", + "ext-tokenizer": "*", + "ext-xmlwriter": "*", + "php": ">=5.4.0" + }, + "require-dev": { + "phpunit/phpunit": "^4.0 || ^5.0 || ^6.0 || ^7.0 || ^8.0 || ^9.3.4" }, + "bin": [ + "bin/phpcbf", + "bin/phpcs" + ], "type": "library", "extra": { "branch-alias": { - "dev-master": "3.0-dev" + "dev-master": "3.x-dev" } }, - "autoload": { - "classmap": [ - "src/" - ] - }, "notification-url": "https://packagist.org/downloads/", "license": [ "BSD-3-Clause" ], "authors": [ { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "lead" + "name": "Greg Sherwood", + "role": "Former lead" + }, + { + "name": "Juliette Reinders Folmer", + "role": "Current lead" + }, + { + "name": "Contributors", + "homepage": "https://github.com/PHPCSStandards/PHP_CodeSniffer/graphs/contributors" } ], - "description": "Library that helps with managing the version number of Git-hosted PHP projects", - "homepage": "https://github.com/sebastianbergmann/version", + "description": "PHP_CodeSniffer tokenizes PHP, JavaScript and CSS files and detects violations of a defined set of coding standards.", + "homepage": "https://github.com/PHPCSStandards/PHP_CodeSniffer", + "keywords": [ + "phpcs", + "standards", + "static analysis" + ], "support": { - "issues": "https://github.com/sebastianbergmann/version/issues", - "source": "https://github.com/sebastianbergmann/version/tree/3.0.2" + "issues": "https://github.com/PHPCSStandards/PHP_CodeSniffer/issues", + "security": "https://github.com/PHPCSStandards/PHP_CodeSniffer/security/policy", + "source": "https://github.com/PHPCSStandards/PHP_CodeSniffer", + "wiki": "https://github.com/PHPCSStandards/PHP_CodeSniffer/wiki" }, "funding": [ { - "url": "https://github.com/sebastianbergmann", + "url": "https://github.com/PHPCSStandards", + "type": "github" + }, + { + "url": "https://github.com/jrfnl", "type": "github" + }, + { + "url": "https://opencollective.com/php_codesniffer", + "type": "open_collective" + }, + { + "url": "https://thanks.dev/u/gh/phpcsstandards", + "type": "thanks_dev" } ], - "time": "2020-09-28T06:39:44+00:00" + "time": "2025-04-13T04:10:18+00:00" }, { - "name": "symfony/polyfill-ctype", - "version": "v1.22.1", + "name": "symfony/config", + "version": "v7.2.6", "source": { "type": "git", - "url": "https://github.com/symfony/polyfill-ctype.git", - "reference": "c6c942b1ac76c82448322025e084cadc56048b4e" + "url": "https://github.com/symfony/config.git", + "reference": "e0b050b83ba999aa77a3736cb6d5b206d65b9d0d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/c6c942b1ac76c82448322025e084cadc56048b4e", - "reference": "c6c942b1ac76c82448322025e084cadc56048b4e", + "url": "https://api.github.com/repos/symfony/config/zipball/e0b050b83ba999aa77a3736cb6d5b206d65b9d0d", + "reference": "e0b050b83ba999aa77a3736cb6d5b206d65b9d0d", "shasum": "" }, "require": { - "php": ">=7.1" + "php": ">=8.2", + "symfony/deprecation-contracts": "^2.5|^3", + "symfony/filesystem": "^7.1", + "symfony/polyfill-ctype": "~1.8" }, - "suggest": { - "ext-ctype": "For best performance" + "conflict": { + "symfony/finder": "<6.4", + "symfony/service-contracts": "<2.5" }, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "1.22-dev" - }, - "thanks": { - "name": "symfony/polyfill", - "url": "https://github.com/symfony/polyfill" - } + "require-dev": { + "symfony/event-dispatcher": "^6.4|^7.0", + "symfony/finder": "^6.4|^7.0", + "symfony/messenger": "^6.4|^7.0", + "symfony/service-contracts": "^2.5|^3", + "symfony/yaml": "^6.4|^7.0" }, + "type": "library", "autoload": { "psr-4": { - "Symfony\\Polyfill\\Ctype\\": "" + "Symfony\\Component\\Config\\": "" }, - "files": [ - "bootstrap.php" + "exclude-from-classmap": [ + "/Tests/" ] }, "notification-url": "https://packagist.org/downloads/", @@ -2209,24 +2683,18 @@ ], "authors": [ { - "name": "Gert de Pagter", - "email": "BackEndTea@gmail.com" + "name": "Fabien Potencier", + "email": "fabien@symfony.com" }, { "name": "Symfony Community", "homepage": "https://symfony.com/contributors" } ], - "description": "Symfony polyfill for ctype functions", + "description": "Helps you find, load, combine, autofill and validate configuration values of any kind", "homepage": "https://symfony.com/", - "keywords": [ - "compatibility", - "ctype", - "polyfill", - "portable" - ], "support": { - "source": "https://github.com/symfony/polyfill-ctype/tree/v1.22.1" + "source": "https://github.com/symfony/config/tree/v7.2.6" }, "funding": [ { @@ -2242,93 +2710,119 @@ "type": "tidelift" } ], - "time": "2021-01-07T16:49:33+00:00" + "time": "2025-04-03T21:14:15+00:00" }, { - "name": "theseer/tokenizer", - "version": "1.2.0", + "name": "symfony/dependency-injection", + "version": "v7.2.6", "source": { "type": "git", - "url": "https://github.com/theseer/tokenizer.git", - "reference": "75a63c33a8577608444246075ea0af0d052e452a" + "url": "https://github.com/symfony/dependency-injection.git", + "reference": "2ca85496cde37f825bd14f7e3548e2793ca90712" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/theseer/tokenizer/zipball/75a63c33a8577608444246075ea0af0d052e452a", - "reference": "75a63c33a8577608444246075ea0af0d052e452a", + "url": "https://api.github.com/repos/symfony/dependency-injection/zipball/2ca85496cde37f825bd14f7e3548e2793ca90712", + "reference": "2ca85496cde37f825bd14f7e3548e2793ca90712", "shasum": "" }, "require": { - "ext-dom": "*", - "ext-tokenizer": "*", - "ext-xmlwriter": "*", - "php": "^7.2 || ^8.0" + "php": ">=8.2", + "psr/container": "^1.1|^2.0", + "symfony/deprecation-contracts": "^2.5|^3", + "symfony/service-contracts": "^3.5", + "symfony/var-exporter": "^6.4.20|^7.2.5" + }, + "conflict": { + "ext-psr": "<1.1|>=2", + "symfony/config": "<6.4", + "symfony/finder": "<6.4", + "symfony/yaml": "<6.4" + }, + "provide": { + "psr/container-implementation": "1.1|2.0", + "symfony/service-implementation": "1.1|2.0|3.0" + }, + "require-dev": { + "symfony/config": "^6.4|^7.0", + "symfony/expression-language": "^6.4|^7.0", + "symfony/yaml": "^6.4|^7.0" }, "type": "library", "autoload": { - "classmap": [ - "src/" + "psr-4": { + "Symfony\\Component\\DependencyInjection\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" ] }, "notification-url": "https://packagist.org/downloads/", "license": [ - "BSD-3-Clause" + "MIT" ], "authors": [ { - "name": "Arne Blankerts", - "email": "arne@blankerts.de", - "role": "Developer" + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" } ], - "description": "A small library for converting tokenized PHP source code into XML and potentially other formats", + "description": "Allows you to standardize and centralize the way objects are constructed in your application", + "homepage": "https://symfony.com/", "support": { - "issues": "https://github.com/theseer/tokenizer/issues", - "source": "https://github.com/theseer/tokenizer/tree/master" + "source": "https://github.com/symfony/dependency-injection/tree/v7.2.6" }, "funding": [ { - "url": "https://github.com/theseer", + "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": "2020-07-12T23:59:07+00:00" + "time": "2025-04-27T13:37:55+00:00" }, { - "name": "webmozart/assert", - "version": "1.10.0", + "name": "symfony/deprecation-contracts", + "version": "v3.5.1", "source": { "type": "git", - "url": "https://github.com/webmozarts/assert.git", - "reference": "6964c76c7804814a842473e0c8fd15bab0f18e25" + "url": "https://github.com/symfony/deprecation-contracts.git", + "reference": "74c71c939a79f7d5bf3c1ce9f5ea37ba0114c6f6" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/webmozarts/assert/zipball/6964c76c7804814a842473e0c8fd15bab0f18e25", - "reference": "6964c76c7804814a842473e0c8fd15bab0f18e25", + "url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/74c71c939a79f7d5bf3c1ce9f5ea37ba0114c6f6", + "reference": "74c71c939a79f7d5bf3c1ce9f5ea37ba0114c6f6", "shasum": "" }, "require": { - "php": "^7.2 || ^8.0", - "symfony/polyfill-ctype": "^1.8" - }, - "conflict": { - "phpstan/phpstan": "<0.12.20", - "vimeo/psalm": "<4.6.1 || 4.6.2" - }, - "require-dev": { - "phpunit/phpunit": "^8.5.13" + "php": ">=8.1" }, "type": "library", "extra": { + "thanks": { + "url": "https://github.com/symfony/contracts", + "name": "symfony/contracts" + }, "branch-alias": { - "dev-master": "1.10-dev" + "dev-main": "3.5-dev" } }, "autoload": { - "psr-4": { - "Webmozart\\Assert\\": "src/" - } + "files": [ + "function.php" + ] }, "notification-url": "https://packagist.org/downloads/", "license": [ @@ -2336,29 +2830,479 @@ ], "authors": [ { - "name": "Bernhard Schussek", - "email": "bschussek@gmail.com" + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" } ], - "description": "Assertions to validate method input/output with nice error messages.", - "keywords": [ - "assert", - "check", - "validate" - ], + "description": "A generic function and convention to trigger deprecation notices", + "homepage": "https://symfony.com/", "support": { - "issues": "https://github.com/webmozarts/assert/issues", - "source": "https://github.com/webmozarts/assert/tree/1.10.0" + "source": "https://github.com/symfony/deprecation-contracts/tree/v3.5.1" + }, + "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-25T14:20:29+00:00" + }, + { + "name": "symfony/filesystem", + "version": "v7.2.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/filesystem.git", + "reference": "b8dce482de9d7c9fe2891155035a7248ab5c7fdb" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/filesystem/zipball/b8dce482de9d7c9fe2891155035a7248ab5c7fdb", + "reference": "b8dce482de9d7c9fe2891155035a7248ab5c7fdb", + "shasum": "" }, - "time": "2021-03-09T10:59:23+00:00" + "require": { + "php": ">=8.2", + "symfony/polyfill-ctype": "~1.8", + "symfony/polyfill-mbstring": "~1.8" + }, + "require-dev": { + "symfony/process": "^6.4|^7.0" + }, + "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/v7.2.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-10-25T15:15:23+00:00" + }, + { + "name": "symfony/polyfill-ctype", + "version": "v1.31.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-ctype.git", + "reference": "a3cc8b044a6ea513310cbd48ef7333b384945638" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/a3cc8b044a6ea513310cbd48ef7333b384945638", + "reference": "a3cc8b044a6ea513310cbd48ef7333b384945638", + "shasum": "" + }, + "require": { + "php": ">=7.2" + }, + "provide": { + "ext-ctype": "*" + }, + "suggest": { + "ext-ctype": "For best performance" + }, + "type": "library", + "extra": { + "thanks": { + "url": "https://github.com/symfony/polyfill", + "name": "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.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-mbstring", + "version": "v1.32.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-mbstring.git", + "reference": "6d857f4d76bd4b343eac26d6b539585d2bc56493" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/6d857f4d76bd4b343eac26d6b539585d2bc56493", + "reference": "6d857f4d76bd4b343eac26d6b539585d2bc56493", + "shasum": "" + }, + "require": { + "ext-iconv": "*", + "php": ">=7.2" + }, + "provide": { + "ext-mbstring": "*" + }, + "suggest": { + "ext-mbstring": "For best performance" + }, + "type": "library", + "extra": { + "thanks": { + "url": "https://github.com/symfony/polyfill", + "name": "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.32.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-12-23T08:48:59+00:00" + }, + { + "name": "symfony/service-contracts", + "version": "v3.5.1", + "source": { + "type": "git", + "url": "https://github.com/symfony/service-contracts.git", + "reference": "e53260aabf78fb3d63f8d79d69ece59f80d5eda0" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/service-contracts/zipball/e53260aabf78fb3d63f8d79d69ece59f80d5eda0", + "reference": "e53260aabf78fb3d63f8d79d69ece59f80d5eda0", + "shasum": "" + }, + "require": { + "php": ">=8.1", + "psr/container": "^1.1|^2.0", + "symfony/deprecation-contracts": "^2.5|^3" + }, + "conflict": { + "ext-psr": "<1.1|>=2" + }, + "type": "library", + "extra": { + "thanks": { + "url": "https://github.com/symfony/contracts", + "name": "symfony/contracts" + }, + "branch-alias": { + "dev-main": "3.5-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Contracts\\Service\\": "" + }, + "exclude-from-classmap": [ + "/Test/" + ] + }, + "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/v3.5.1" + }, + "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-25T14:20:29+00:00" + }, + { + "name": "symfony/var-exporter", + "version": "v7.2.6", + "source": { + "type": "git", + "url": "https://github.com/symfony/var-exporter.git", + "reference": "422b8de94c738830a1e071f59ad14d67417d7007" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/var-exporter/zipball/422b8de94c738830a1e071f59ad14d67417d7007", + "reference": "422b8de94c738830a1e071f59ad14d67417d7007", + "shasum": "" + }, + "require": { + "php": ">=8.2" + }, + "require-dev": { + "symfony/property-access": "^6.4|^7.0", + "symfony/serializer": "^6.4|^7.0", + "symfony/var-dumper": "^6.4|^7.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\VarExporter\\": "" + }, + "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": "Allows exporting any serializable PHP data structure to plain PHP code", + "homepage": "https://symfony.com/", + "keywords": [ + "clone", + "construct", + "export", + "hydrate", + "instantiate", + "lazy-loading", + "proxy", + "serialize" + ], + "support": { + "source": "https://github.com/symfony/var-exporter/tree/v7.2.6" + }, + "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": "2025-05-02T08:36:00+00:00" + }, + { + "name": "theseer/tokenizer", + "version": "1.2.3", + "source": { + "type": "git", + "url": "https://github.com/theseer/tokenizer.git", + "reference": "737eda637ed5e28c3413cb1ebe8bb52cbf1ca7a2" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/theseer/tokenizer/zipball/737eda637ed5e28c3413cb1ebe8bb52cbf1ca7a2", + "reference": "737eda637ed5e28c3413cb1ebe8bb52cbf1ca7a2", + "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.3" + }, + "funding": [ + { + "url": "https://github.com/theseer", + "type": "github" + } + ], + "time": "2024-03-03T12:36:25+00:00" } ], "aliases": [], "minimum-stability": "stable", - "stability-flags": [], + "stability-flags": {}, "prefer-stable": false, "prefer-lowest": false, - "platform": [], - "platform-dev": [], - "plugin-api-version": "2.0.0" + "platform": { + "php": ">=8.1" + }, + "platform-dev": {}, + "plugin-api-version": "2.6.0" } diff --git a/example/01-posted-form-triggers-function.php b/example/01-posted-form-triggers-function.php new file mode 100644 index 0000000..75db8a4 --- /dev/null +++ b/example/01-posted-form-triggers-function.php @@ -0,0 +1,52 @@ + "Eugene Kaspersky", + "card-number" => "4111011101110111", + "card-expiry" => "23/11", + "card-cvv" => "359", + "address" => "14 Brooke Street", + "do" => "pay", +]; +$_FILES = []; + +$input = new Input($_GET, $_POST, $_FILES); + +$input->do("pay") + ->call("processCard"); + +$input->do("pay") + ->with("name", "address") + ->call("processShipping"); + +function processCard(InputData $data) { + echo "Executing processCard...", PHP_EOL; + foreach($data as $key => $value) { + echo "processCard InputData: $key = $value", PHP_EOL; + } + echo PHP_EOL; +} + +function processShipping(InputData $data) { + echo "Executing processShipping...", PHP_EOL; + echo "Name: ", $data->getString("name"), PHP_EOL; + echo "Address: ", $data->getString("address"), PHP_EOL; + echo "Credit card: ", $data->getString("card-number") ?? "DATA NOT PASSED!", PHP_EOL; +} diff --git a/example/02-multiple-inputs.php b/example/02-multiple-inputs.php new file mode 100644 index 0000000..d2045da --- /dev/null +++ b/example/02-multiple-inputs.php @@ -0,0 +1,107 @@ + + *
+ *
+ *
+ *
+ *
+ * + * + *
+ */ +use Gt\Input\Input; +use Gt\Input\InputData\Datum\FailedFileUpload; + +require(__DIR__ . "/../vendor/autoload.php"); + +$_GET = []; +$_POST = [ + "do" => "upload", + "name" => "Greg", + "colour" => [ + "red", + "blue", + ], +]; +$_FILES = [ + "upload" => [ + "name" => [ + "front.jpg", + "back.jpg", + "description.txt", + ], + "full_path" => [ + "front.jpg", + "back.jpg", + "description.txt", + ], + "type" => [ + "image/jpeg", + "image/jpeg", + "text/plain", + ], + "tmp_name" => [ + "/tmp/phpkLgfwE", + "/tmp/phpiZKQf6", + "/tmp/php9UtO5A", + ], + "error" => [ + 0, + 0, + 0, + ], + "size" => [ + 123891, + 165103, + 915, + ], + ] +]; + +$input = new Input($_GET, $_POST, $_FILES); + +echo "Your name: " . $input->getString("name"), PHP_EOL; + +if(!$input->contains("colour")) { + echo "No colours chosen...", PHP_EOL; + exit; +} +foreach($input->getMultipleString("colour") as $colour) { + echo "Colour chosen: $colour", PHP_EOL; +} + +if(!$input->contains("upload")) { + echo "Nothing uploaded...", PHP_EOL; + exit; +} + +foreach($input->getMultipleFile("upload") as $fileName => $upload) { + if($upload instanceof FailedFileUpload) { + echo "Error uploading $fileName!", PHP_EOL; + continue; + } + + $newPath = "data/upload/$fileName"; + $size = $upload->getSize(); + echo "Uploaded to $newPath (size $size)", PHP_EOL; +} diff --git a/example/www/multiple-file-upload.php b/example/www/multiple-file-upload.php new file mode 100644 index 0000000..d3052de --- /dev/null +++ b/example/www/multiple-file-upload.php @@ -0,0 +1,47 @@ +"; +echo "Your name is: ", $input->getString("name"), PHP_EOL; + +$colourString = implode(", ", $input->getMultipleString("colour")); +echo "Colours chosen: ", $colourString, PHP_EOL; + +echo "Files uploaded: ", PHP_EOL; +foreach($input->getMultipleFile("upload") as $fileName => $upload) { + echo "$fileName is size: ", $upload->getSize(), PHP_EOL; +} + +website:?> + +
+
+
+
+
+ + +
diff --git a/phpcs.xml b/phpcs.xml new file mode 100644 index 0000000..b771656 --- /dev/null +++ b/phpcs.xml @@ -0,0 +1,61 @@ + + + Created from PHP.Gt/Styleguide + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/phpmd.xml b/phpmd.xml new file mode 100644 index 0000000..5424e30 --- /dev/null +++ b/phpmd.xml @@ -0,0 +1,44 @@ + + + Custom ruleset + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/phpunit.xml b/phpunit.xml new file mode 100644 index 0000000..5e1b5d9 --- /dev/null +++ b/phpunit.xml @@ -0,0 +1,28 @@ + + + + + + + + ./test/phpunit/ + + + + + + + + + + src/ + + + + diff --git a/src/BodyStream.php b/src/BodyStream.php index b7eef95..9b87fd1 100644 --- a/src/BodyStream.php +++ b/src/BodyStream.php @@ -3,4 +3,4 @@ use Gt\Http\Stream; -class BodyStream extends Stream {} \ No newline at end of file +class BodyStream extends Stream {} diff --git a/src/CallOrOutOfSequenceException.php b/src/CallOrOutOfSequenceException.php index 2c70dc6..b05381f 100644 --- a/src/CallOrOutOfSequenceException.php +++ b/src/CallOrOutOfSequenceException.php @@ -1,4 +1,4 @@ + * @implements Iterator + * @SuppressWarnings(PHPMD.CouplingBetweenObjects) + * @SuppressWarnings(PHPMD.TooManyPublicMethods) + */ class Input implements ArrayAccess, Countable, Iterator { use InputValueGetter; use KeyValueArrayAccess; @@ -27,19 +37,21 @@ class Input implements ArrayAccess, Countable, Iterator { const DATA_FILES = "files"; const DATA_COMBINED = "combined"; - /** @var BodyStream */ - protected $bodyStream; - - /** @var QueryStringInputData */ - protected $queryStringParameters; - /** @var BodyInputData */ - protected $bodyParameters; + protected BodyStream $bodyStream; + protected QueryStringInputData $queryStringParameters; + protected BodyInputData $bodyParameters; + /** + * @param array $get + * @param array $post + * @param array>> $files + * @param string $bodyPath + */ public function __construct( array $get = [], array $post = [], array $files = [], - string $bodyPath = "php://input" + string $bodyPath = "php://input", ) { $this->bodyStream = new BodyStream($bodyPath); @@ -89,7 +101,6 @@ public function add(string $key, InputDatum $datum, string $method):void { default: throw new InvalidInputMethodException($method); - break; } $this->parameters = new CombinedInputData( @@ -100,46 +111,30 @@ public function add(string $key, InputDatum $datum, string $method):void { } /** - * Get a particular input value by its key. To specify either GET or POST variables, pass - * Input::METHOD_GET or Input::METHOD_POST as the second parameter (defaults to - * Input::METHOD_BOTH). - * @return mixed|null + * Get a particular input value by its key. To specify either GET or + * POST variables, pass Input::METHOD_GET or Input::METHOD_POST as the + * second parameter (defaults to Input::METHOD_BOTH). */ - public function get(string $key, string $method = null) { + public function get(string $key, ?string $method = null):mixed { if(is_null($method)) { $method = self::DATA_COMBINED; } - $data = null; - - switch($method) { - case self::DATA_QUERYSTRING: - $data = $this->queryStringParameters->get($key); - break; - - case self::DATA_BODY: - $data =$this->bodyParameters->get($key); - break; + $data = match($method) { + self::DATA_QUERYSTRING => $this->queryStringParameters->get($key), + self::DATA_BODY => $this->bodyParameters->get($key), + self::DATA_FILES => $this->fileUploadParameters->getFile($key), + self::DATA_COMBINED => $this->parameters->get($key), + default => throw new InvalidInputMethodException($method), + }; - case self::DATA_FILES: - $data = $this->fileUploadParameters->getFile($key); - break; - - case self::DATA_COMBINED: - $data = $this->parameters->get($key); - break; - - default: - throw new InvalidInputMethodException($method); - } - - return $data; + return $data?->getValue(); } /** * Does the input contain the specified key? */ - public function contains(string $key, string $method = null):bool { + public function contains(string $key, ?string $method = null):bool { if(is_null($method)) { $method = self::DATA_COMBINED; } @@ -181,10 +176,11 @@ public function containsFile(string $key):bool { } /** - * Get an InputData object containing all request variables. To specify only GET or POST - * variables, pass Input::METHOD_GET or Input::METHOD_POST. + * Get an InputData object containing all request variables. To specify + * only GET or POST variables, pass Input::METHOD_GET + * or Input::METHOD_POST. */ - public function getAll(string $method = null):InputData { + public function getAll(?string $method = null):InputData { if(is_null($method)) { $method = self::DATA_COMBINED; } @@ -203,6 +199,17 @@ public function getAll(string $method = null):InputData { } } + public function getBodyJson():?JsonObject { + $jsonBuilder = new JsonObjectBuilder(); + + try { + return $jsonBuilder->fromJsonString($this->bodyStream->getContents()); + } + catch(JsonDecodeException) { + return null; + } + } + /** * Return a "do" Trigger, matching when a request variable is present with the * provided $match value. @@ -212,13 +219,16 @@ public function do(string $match):Trigger { } /** - * Return a Trigger, firing when one or more request variables are present with - * the provided key value pair(s) are present. + * Return a Trigger, firing when one or more request variables are + * present with the provided key value pair(s) are present. * - * $matches is an associative array, where the key is a request variable's name and the - * value is the request variable's value to match. + * $matches is an associative array, where the key is a request + * variable's name and the value is the request variable's value + * to match. + * + * @param array|string $matches */ - public function when(...$matches):Trigger { + public function when(array|string...$matches):Trigger { $trigger = new Trigger($this); $trigger->when($matches); return $trigger; @@ -227,31 +237,63 @@ public function when(...$matches):Trigger { /** * Return a Trigger that will only pass the provided keys to its callback. */ - public function with(string...$keys):Trigger { + public function select(string...$keys):Trigger { foreach($keys as $key) { if(!$this->parameters->contains($key)) { throw new MissingInputParameterException($key); } } - return $this->newTrigger("with", ...$keys); + return $this->newTrigger("select", ...$keys); + } + + /** @deprecated Use select() instead to avoid ambiguity with immutable `with` functions */ + public function with(string...$keys):Trigger { + return $this->select(...$keys); + } + + /** @SuppressWarnings(PHPMD.UnusedLocalVariable) */ + public function selectPrefix(string $prefix):Trigger { + $keys = []; + + foreach($this->parameters as $key => $param) { + if(str_starts_with($key, $prefix)) { + array_push($keys, $key); + } + } + + if($keys) { + return $this->when(...$keys); + } + else { + return new NeverTrigger($this); + } } /** - * Return a Trigger that will pass all keys apart from the provided keys to its callback. + * Return a Trigger that will pass all keys apart from the provided + * keys to its callback. */ - public function without(string...$keys):Trigger { + public function selectAllExcept(string...$keys):Trigger { return $this->newTrigger("without", ...$keys); } + /** @deprecated Use selectAllExcept() instead to avoid ambiguity with immutable `with` functions */ + public function without(string...$keys):Trigger { + return $this->selectAllExcept(...$keys); + } /** * Return a Trigger that will pass all keys to its callback. */ - public function withAll():Trigger { + public function selectAll():Trigger { return $this->newTrigger("withAll"); } + /** @deprecated Use selectAll() instead to avoid ambiguity with immutable `with` functions */ + public function withAll():Trigger { + return $this->selectAll(); + } - protected function newTrigger(string $functionName, ...$args):Trigger { + protected function newTrigger(string $functionName, string...$args):Trigger { $trigger = new Trigger($this); return $trigger->$functionName(...$args); } diff --git a/src/InputData/AbstractInputData.php b/src/InputData/AbstractInputData.php index 6e31ecf..638a50e 100644 --- a/src/InputData/AbstractInputData.php +++ b/src/InputData/AbstractInputData.php @@ -3,23 +3,25 @@ use ArrayAccess; use Countable; +use Gt\Input\InputData\Datum\MultipleInputDatum; use Gt\Input\InputValueGetter; use Iterator; use Gt\Input\InputData\Datum\InputDatum; +/** + * @implements ArrayAccess + * @implements Iterator + */ abstract class AbstractInputData implements ArrayAccess, Countable, Iterator { use InputValueGetter; use KeyValueArrayAccess; use KeyValueCountable; use KeyValueIterator; - /** @var QueryStringInputData */ - protected $queryStringParameters; - /** @var BodyInputData */ - protected $bodyParameters; + protected QueryStringInputData $queryStringParameters; + protected BodyInputData $bodyParameters; - /** @return mixed|null */ - public function get(string $key) { + public function get(string $key):mixed { return $this->parameters[$key] ?? null; } @@ -33,12 +35,12 @@ public function hasValue(string $key):bool { } protected function set(string $key, InputDatum $value):void { - $this->parameters[$key] = $value; + $this->parameters[$key] = (string)$value; } - public function withKeyValue(string $key, InputDatum $value):self { + public function withKeyValue(string $key, InputDatum $value):static { $clone = clone($this); - $clone->parameters[$key] = $value; + $clone->parameters[$key] = (string)$value; return $clone; } } diff --git a/src/InputData/BodyInputData.php b/src/InputData/BodyInputData.php index 4d7863a..452e5d1 100644 --- a/src/InputData/BodyInputData.php +++ b/src/InputData/BodyInputData.php @@ -1,4 +1,4 @@ errorCode; } @@ -44,10 +31,12 @@ public function getErrorMessage():string { switch($this->errorCode) { case UPLOAD_ERR_INI_SIZE: - $msg = "The uploaded file exceeds the upload_max_filesize directive in php.ini."; + $msg = "The uploaded file exceeds the " + . "upload_max_filesize directive in php.ini."; break; case UPLOAD_ERR_FORM_SIZE: - $msg = "The uploaded file exceeds the MAX_FILE_SIZE directive that was specified in the HTML form."; + $msg = "The uploaded file exceeds the MAX_FILE_SIZE " + . "directive that was specified in the HTML form."; break; case UPLOAD_ERR_PARTIAL: $msg = "The uploaded file was only partially uploaded."; @@ -68,4 +57,4 @@ public function getErrorMessage():string { return $msg; } -} \ No newline at end of file +} diff --git a/src/InputData/Datum/FileUpload.php b/src/InputData/Datum/FileUpload.php index 4816643..edca476 100644 --- a/src/InputData/Datum/FileUpload.php +++ b/src/InputData/Datum/FileUpload.php @@ -56,22 +56,7 @@ public function getMimeType():string { return $this->mimeType; } - /** - * Retrieve a stream representing the uploaded file. - * - * This method MUST return a StreamInterface instance, representing the - * uploaded file. The purpose of this method is to allow utilizing native PHP - * stream functionality to manipulate the file upload, such as - * stream_copy_to_stream() (though the result will need to be decorated in a - * native PHP stream wrapper to work with such functions). - * - * If the moveTo() method has been called previously, this method MUST raise - * an exception. - * - * @return StreamInterface Stream representation of the uploaded file. - * @throws \RuntimeException in cases when no stream is available or can be - * created. - */ + /** @inheritDoc */ public function getStream():StreamInterface { if($this->moved) { throw new StreamNotAvailableException("File has been moved"); @@ -79,47 +64,12 @@ public function getStream():StreamInterface { return new Stream($this->getRealPath()); } - /** - * Move the uploaded file to a new location. - * - * Use this method as an alternative to move_uploaded_file(). This method is - * guaranteed to work in both SAPI and non-SAPI environments. - * Implementations must determine which environment they are in, and use the - * appropriate method (move_uploaded_file(), rename(), or a stream - * operation) to perform the operation. - * - * $targetPath may be an absolute path, or a relative path. If it is a - * relative path, resolution should be the same as used by PHP's rename() - * function. - * - * The original file or stream MUST be removed on completion. - * - * If this method is called more than once, any subsequent calls MUST raise - * an exception. - * - * When used in an SAPI environment where $_FILES is populated, when writing - * files via moveTo(), is_uploaded_file() and move_uploaded_file() SHOULD be - * used to ensure permissions and upload status are verified correctly. - * - * If you wish to move to a stream, use getStream(), as SAPI operations - * cannot guarantee writing to stream destinations. - * - * @see http://php.net/is_uploaded_file - * @see http://php.net/move_uploaded_file - * @param string $targetPath Path to which to move the uploaded file. - * @throws InvalidArgumentException if the $targetPath specified is invalid. - * @throws \RuntimeException on any error during the move operation, or on - * the second or subsequent call to the method. - */ - public function moveTo($targetPath) { + /** @inheritDoc */ + public function moveTo(string $targetPath):void { if(!is_uploaded_file($this->tempFilePath)) { throw new UploadedFileSecurityException($this->tempFilePath); } - if(!is_string($targetPath)) { - throw new TypeError("Argument 1 passed to " . __METHOD__ . " must be of type string, " . gettype($targetPath) . "given"); - } - $targetPath = str_replace( ["/", "\\"], DIRECTORY_SEPARATOR, @@ -142,57 +92,20 @@ public function moveTo($targetPath) { $this->moved = true; } - /** - * Retrieve the error associated with the uploaded file. - * - * The return value MUST be one of PHP's UPLOAD_ERR_XXX constants. - * - * If the file was uploaded successfully, this method MUST return - * UPLOAD_ERR_OK. - * - * Implementations SHOULD return the value stored in the "error" key of - * the file in the $_FILES array. - * - * @see http://php.net/manual/en/features.file-upload.errors.php - * @return int One of PHP's UPLOAD_ERR_XXX constants. - */ - public function getError() { -// Note that this class ALWAYS returns UPLOAD_ERR_OK, due to failed uploads being -// represented by another class, FailedFileUpload. + /** @inheritDoc */ + public function getError():int { +// Note that this class ALWAYS returns UPLOAD_ERR_OK, due to failed uploads +// being represented by another class, FailedFileUpload. return UPLOAD_ERR_OK; } - /** - * Retrieve the filename sent by the client. - * - * Do not trust the value returned by this method. A client could send - * a malicious filename with the intention to corrupt or hack your - * application. - * - * Implementations SHOULD return the value stored in the "name" key of - * the file in the $_FILES array. - * - * @return string|null The filename sent by the client or null if none - * was provided. - */ - public function getClientFilename() { + /** @inheritDoc */ + public function getClientFilename():?string { return $this->originalFileName; } - /** - * Retrieve the media type sent by the client. - * - * Do not trust the value returned by this method. A client could send - * a malicious media type with the intention to corrupt or hack your - * application. - * - * Implementations SHOULD return the value stored in the "type" key of - * the file in the $_FILES array. - * - * @return string|null The media type sent by the client or null if none - * was provided. - */ - public function getClientMediaType() { + /** @inheritDoc */ + public function getClientMediaType():?string { return $this->getMimeType(); } -} \ No newline at end of file +} diff --git a/src/InputData/Datum/InputDatum.php b/src/InputData/Datum/InputDatum.php index b0d44e0..f1405e7 100644 --- a/src/InputData/Datum/InputDatum.php +++ b/src/InputData/Datum/InputDatum.php @@ -2,13 +2,17 @@ namespace Gt\Input\InputData\Datum; class InputDatum { - protected $value; + protected mixed $value; - public function __construct($value) { + public function __construct(mixed $value) { $this->value = $value; } public function __toString():string { return $this->value; } -} \ No newline at end of file + + public function getValue():mixed { + return $this->value; + } +} diff --git a/src/InputData/Datum/MultipleInputDatum.php b/src/InputData/Datum/MultipleInputDatum.php index c676509..30ee053 100644 --- a/src/InputData/Datum/MultipleInputDatum.php +++ b/src/InputData/Datum/MultipleInputDatum.php @@ -5,10 +5,15 @@ use Gt\Input\ImmutableObjectModificationException; use Iterator; +/** + * @implements ArrayAccess + * @implements Iterator + * @SuppressWarnings("TooManyPublicMethods") + */ class MultipleInputDatum extends InputDatum implements ArrayAccess, Iterator { - protected $iteratorKey; + protected int $iteratorKey; - public function __construct($value) { + public function __construct(mixed $value) { parent::__construct($value); $this->iteratorKey = 0; @@ -18,6 +23,7 @@ public function __toString():string { return implode(", ", $this->value); } + /** @return array */ public function toArray():array { $array = []; @@ -31,7 +37,7 @@ public function toArray():array { /** * @link http://php.net/manual/en/iterator.current.php */ - public function current() { + public function current():mixed { return $this->offsetGet($this->iteratorKey); } @@ -63,31 +69,38 @@ public function rewind():void { $this->iteratorKey = 0; } - /** - * @link http://php.net/manual/en/arrayaccess.offsetexists.php + /** @link http://php.net/manual/en/arrayaccess.offsetexists.php + * @param string|int $offset */ public function offsetExists($offset):bool { return isset($this->value[$offset]); } - /** - * @link http://php.net/manual/en/arrayaccess.offsetget.php + /** @link http://php.net/manual/en/arrayaccess.offsetget.php + * @param string|int $offset */ - public function offsetGet($offset) { + public function offsetGet($offset):mixed { return $this->value[$offset]; } /** * @link http://php.net/manual/en/arrayaccess.offsetset.php + * @param string|int $offset + * @param string $value + * @SuppressWarnings("UnusedFormalParameter") */ public function offsetSet($offset, $value):void { - throw new ImmutableObjectModificationException(); + throw new ImmutableObjectModificationException( + "Trying to set $offset with $value" + ); } /** * @link http://php.net/manual/en/arrayaccess.offsetunset.php + * @param string|int $offset + * @SuppressWarnings("UnusedFormalParameter") */ public function offsetUnset($offset):void { - throw new ImmutableObjectModificationException(); + throw new ImmutableObjectModificationException("Trying to unset $offset"); } -} \ No newline at end of file +} diff --git a/src/InputData/Datum/StreamNotAvailableException.php b/src/InputData/Datum/StreamNotAvailableException.php index 0a0c43e..f64c1e6 100644 --- a/src/InputData/Datum/StreamNotAvailableException.php +++ b/src/InputData/Datum/StreamNotAvailableException.php @@ -3,4 +3,4 @@ use Gt\Input\InputException; -class StreamNotAvailableException extends InputException {} \ No newline at end of file +class StreamNotAvailableException extends InputException {} diff --git a/src/InputData/FileUploadInputData.php b/src/InputData/FileUploadInputData.php index 87736d9..4696fab 100644 --- a/src/InputData/FileUploadInputData.php +++ b/src/InputData/FileUploadInputData.php @@ -5,7 +5,9 @@ use Gt\Input\InputData\Datum\FileUpload; class FileUploadInputData extends InputData { - + /** + * @param array> $files + */ public function __construct(array $files) { $files = $this->normalizeArray($files); $data = $this->createData($files); @@ -13,17 +15,22 @@ public function __construct(array $files) { } /** - * The files array is an associative array where the key is the name of the request - * parameter, and the value is another associative array with keys: + * The files array is an associative array where the key is the name of + * the request parameter, and the value is another associative array + * with keys: * + name * + type * + tmp_name * + error * + size - * Each key's value is string, unless the request parameter name ends with [], in which case - * each value is another array. This function normalises the array to the latter. + * Each key's value is string, unless the request parameter name ends + * with [], in which case each value is another array. This function + * normalises the array to the latter. + * + * @param array>> $files + * @return array>> */ - protected function normalizeArray($files):array { + protected function normalizeArray(array $files):array { foreach($files as $parameterName => $fileDetailArray) { foreach($fileDetailArray as $key => $value) { if(!is_array($value)) { @@ -35,13 +42,17 @@ protected function normalizeArray($files):array { return $files; } + /** + * @param array>> $files + * @return array> + */ protected function createData(array $files):array { $datumList = []; foreach($files as $inputName => $details) { $datumList[$inputName] = []; - foreach($details["tmp_name"] as $i => $tmpPath) { + foreach(array_keys($details["tmp_name"]) as $i) { $params = [ $details["name"][$i], $details["type"][$i], @@ -49,15 +60,22 @@ protected function createData(array $files):array { $details["tmp_name"][$i], ]; - if($details["error"][$i] === UPLOAD_ERR_OK) { - $datumList[$inputName] []= new FileUpload(...$params); + if($details["error"][$i] == UPLOAD_ERR_OK) { + array_push( + $datumList[$inputName], + new FileUpload(...$params) + ); } else { $params []= (int)$details["error"][$i]; - $datumList[$inputName] []= new FailedFileUpload(...$params); + array_push( + $datumList[$inputName], + new FailedFileUpload(...$params) + ); } } } + return $datumList; } -} \ No newline at end of file +} diff --git a/src/InputData/InputData.php b/src/InputData/InputData.php index 7ad7135..0ea6929 100644 --- a/src/InputData/InputData.php +++ b/src/InputData/InputData.php @@ -6,6 +6,7 @@ use Gt\Input\InputValueGetter; class InputData extends AbstractInputData { + /** @param iterable|iterable>|iterable...$sources */ public function __construct(iterable...$sources) { $this->parameters = []; @@ -15,7 +16,7 @@ public function __construct(iterable...$sources) { && isset($value[0])) { $value = new MultipleInputDatum($value); } - else if(!$value instanceof InputDatum) { + else { $value = new InputDatum($value); } $this->add($key, $value); @@ -44,7 +45,7 @@ public function remove(string...$keys):self { } public function removeExcept(string...$keys):self { - foreach($this->parameters as $key => $value) { + foreach(array_keys($this->parameters) as $key) { if(!in_array($key, $keys)) { unset($this->parameters[$key]); } @@ -53,10 +54,12 @@ public function removeExcept(string...$keys):self { return $this; } + /** @return array */ public function getKeys():array { return array_keys($this->parameters); } + /** @return array> */ public function asArray():array { $array = []; diff --git a/src/InputData/InputDataFactory.php b/src/InputData/InputDataFactory.php index 6d8720f..618f900 100644 --- a/src/InputData/InputDataFactory.php +++ b/src/InputData/InputDataFactory.php @@ -5,7 +5,15 @@ use Gt\Input\WithWithoutClashingException; class InputDataFactory { - public static function create(Input $input, array $with = [], array $without = []):InputData { + /** + * @param array|array $with + * @param array|array $without + */ + public static function create( + Input $input, + array $with = [], + array $without = [], + ):InputData { $data = $input->getAll(); if(empty($with) @@ -13,7 +21,8 @@ public static function create(Input $input, array $with = [], array $without = [ return $data; } -// It's fine to call $input->with()->without, but not if the same value exists in with and without. +// It's fine to call $input->with()->without, but not if the same value exists +// in with and without. if(!empty($with) && !empty($without)) { $clash = array_intersect($with, $without); @@ -34,4 +43,4 @@ public static function create(Input $input, array $with = [], array $without = [ return $data; } -} \ No newline at end of file +} diff --git a/src/InputData/KeyValueArrayAccess.php b/src/InputData/KeyValueArrayAccess.php index df353cc..7102f83 100644 --- a/src/InputData/KeyValueArrayAccess.php +++ b/src/InputData/KeyValueArrayAccess.php @@ -9,12 +9,11 @@ public function offsetExists($offset):bool { return isset($this->parameters[$offset]); } - /** @return mixed|null */ - public function offsetGet($offset) { + public function offsetGet($offset):mixed { if($this instanceof FileUploadInputData) { return $this->getFile($offset); } - elseif($this instanceof Input || $this instanceof InputData) { + elseif(is_a($this, Input::class) || is_a($this, InputData::class)) { if($this->contains($offset)) { return $this->get($offset); } @@ -23,6 +22,10 @@ public function offsetGet($offset) { return null; } + /** + * @param string $offset + * @param string|InputDatum $value + */ public function offsetSet($offset, $value):void { if($this->parameters instanceof InputData) { if(is_string($value)) { @@ -42,7 +45,7 @@ public function offsetSet($offset, $value):void { } } - public function offsetUnset($offset) { + public function offsetUnset($offset):void { if($this->parameters instanceof InputData) { $this->parameters->remove($offset); } @@ -50,4 +53,4 @@ public function offsetUnset($offset) { unset($this->parameters[$offset]); } } -} \ No newline at end of file +} diff --git a/src/InputData/KeyValueCountable.php b/src/InputData/KeyValueCountable.php index 6f2b5a6..f119178 100644 --- a/src/InputData/KeyValueCountable.php +++ b/src/InputData/KeyValueCountable.php @@ -5,4 +5,4 @@ trait KeyValueCountable { public function count():int { return count($this->parameters); } -} \ No newline at end of file +} diff --git a/src/InputData/KeyValueIterator.php b/src/InputData/KeyValueIterator.php index a9ac334..ac052c7 100644 --- a/src/InputData/KeyValueIterator.php +++ b/src/InputData/KeyValueIterator.php @@ -19,11 +19,11 @@ public function key():string { return $this->getIteratorDataKey(); } - public function valid() { + public function valid():bool { return !empty($this->getIteratorDataKey()); } - public function rewind() { + public function rewind():void { $this->iteratorKey = 0; } @@ -39,4 +39,4 @@ protected function getIteratorDataKey():?string { return $keys[$this->iteratorKey] ?? null; } -} \ No newline at end of file +} diff --git a/src/InputData/QueryStringInputData.php b/src/InputData/QueryStringInputData.php index 76a15d5..65924ee 100644 --- a/src/InputData/QueryStringInputData.php +++ b/src/InputData/QueryStringInputData.php @@ -1,4 +1,4 @@ |CombinedInputData */ + protected array|CombinedInputData $parameters; public function getString(string $key):?string { return $this->get($key); } + /** @return array */ + public function getMultipleString(string $key):array { + return $this->getTypedArray($key, "string"); + } + public function getInt(string $key):?int { $value = $this->getString($key); if(is_null($value) || strlen($value) === 0) { @@ -31,6 +35,11 @@ public function getInt(string $key):?int { return (int)$value; } + /** @return array */ + public function getMultipleInt(string $key):array { + return $this->getTypedArray($key, "int"); + } + public function getFloat(string $key):?float { $value = $this->getString($key); if(is_null($value) || strlen($value) === 0) { @@ -40,6 +49,11 @@ public function getFloat(string $key):?float { return (float)$value; } + /** @return array */ + public function getMultipleFloat(string $key):array { + return $this->getTypedArray($key, "float"); + } + public function getBool(string $key):?bool { $value = $this->getString($key); if(is_null($value) || strlen($value) === 0) { @@ -49,36 +63,56 @@ public function getBool(string $key):?bool { return (bool)$value; } - public function getFile(string $key):FileUpload { + /** @return array */ + public function getMultipleBool(string $key):array { + return $this->getTypedArray($key, "bool"); + } + + + public function getFile(string $key):?FileUpload { /** @var FileUploadInputData|InputDatum[] $params */ $params = $this->fileUploadParameters ?? $this->parameters; - try { + /** @var MultipleInputDatum|FileUpload|null $file */ + $file = $params[$key] ?? null; - /** @var MultipleInputDatum|FileUpload $file */ - $file = $params[$key]; + if(is_null($file)) { + return null; + } + try { if($file instanceof MultipleInputDatum) { return $file->current(); } return $file; } - catch(TypeError $exception) { + catch(TypeError) { throw new DataNotFileUploadException($key); } } - /** - * @return FileUpload[] - */ - public function getMultipleFile(string $key):MultipleInputDatum { - return $this->get($key); + /** @return array */ + public function getMultipleFile(string $key):array { + $multipleFileUpload = $this->get($key); + if(!$multipleFileUpload instanceof MultipleInputDatum) { + throw new InputException("Parameter '$key' is not a multiple file input."); + } + + $array = []; + + /** @var FileUpload $file */ + foreach($multipleFileUpload as $file) { + $name = $file->getClientFilename(); + $array[$name] = $file; + } + + return $array; } public function getDateTime( string $key, - string $format = null + ?string $format = null ):?DateTimeInterface { $value = $this->getString($key); if(is_null($value) || strlen($value) === 0) { @@ -87,13 +121,13 @@ public function getDateTime( try { if($format) { - $dateTime = DateTime::createFromFormat($format, $value); + $dateTime = date_create_from_format($format, $value); } else { $dateTime = new DateTime($value); } } - catch(Exception $exception) { + catch(Exception) { $dateTime = false; } @@ -104,10 +138,32 @@ public function getDateTime( return $dateTime; } - /** - * @return DateTime[] - */ - public function getMultipleDateTime(string $key):MultipleInputDatum { + /** @return array */ + public function getMultipleDateTime(string $key):array { return $this->get($key); } + + /** @return array */ + private function getTypedArray(string $key, string $typeName):array { + $array = []; + /** @var null|iterable $datum */ + $datum = $this->get($key); + + if(is_null($datum)) { + return []; + } + + foreach($datum as $item) { + $cast = match($typeName) { + "int" => (int)$item, + "float" => (float)$item, + "bool" => (bool)$item, + default => (string)$item, + }; + + array_push($array, $cast); + } + + return $array; + } } diff --git a/src/InvalidInputMethodException.php b/src/InvalidInputMethodException.php index b1a5164..1bbf524 100644 --- a/src/InvalidInputMethodException.php +++ b/src/InvalidInputMethodException.php @@ -1,4 +1,4 @@ */ + private array $args; - public function __construct(callable $callback, ...$args) { + public function __construct(callable $callback, string...$args) { $this->callback = $callback; $this->args = $args; } public function call(InputData $data):void { - // TODO: Issue #8 Rather than passing all fields into the first parameter, pass them individually. +// TODO: Issue #8 Rather than passing all fields into the first parameter, +// pass them individually. // @see https://github.com/PhpGt/Input/issues/8 $parameters = [$data]; foreach($this->args as $arg) { @@ -23,4 +25,4 @@ public function call(InputData $data):void { call_user_func_array($this->callback, $parameters); } -} \ No newline at end of file +} diff --git a/src/Trigger/NeverTrigger.php b/src/Trigger/NeverTrigger.php new file mode 100644 index 0000000..742b319 --- /dev/null +++ b/src/Trigger/NeverTrigger.php @@ -0,0 +1,18 @@ +> */ + protected array $matches; + /** @var array */ + protected array $keyMatches; + /** @var array */ + protected array $select; + /** @var array */ + protected array $selectAllExcept; + /** @var array */ + protected array $callbacks; + protected ?bool $hasFired; + private InputDataFactory $inputDataFactory; public function __construct(Input $input) { + $this->inputDataFactory = new InputDataFactory(); $this->input = $input; $this->matches = []; $this->keyMatches = []; - $this->with = []; - $this->without = []; + $this->select = []; + $this->selectAllExcept = []; $this->callbacks = []; $this->hasFired = null; } - public function when(...$matches):self { + /** @param string|array...$matches */ + public function when(string|array...$matches):self { $matches = $this->flattenArray($matches); foreach($matches as $key => $match) { @@ -44,28 +49,40 @@ public function when(...$matches):self { return $this; } - public function with(string...$keys):self { + public function select(string...$keys):self { foreach($keys as $key) { - $this->with []= $key; + $this->select []= $key; } return $this; } + /** @deprecated Use select() instead to avoid ambiguity with immutable `with` functions */ + public function with(string...$keys):self { + return $this->select(...$keys); + } - public function without(string...$keys):self { + public function selectAllExcept(string...$keys):self { foreach($keys as $key) { - $this->without []= $key; + $this->selectAllExcept []= $key; } return $this; } + /** @deprecated Use selectAllExcept() instead to avoid ambiguity with immutable `with` functions */ + public function without(string...$keys):self { + return $this->selectAllExcept(...$keys); + } - public function withAll():self { - $this->with = []; - $this->without = []; + public function selectAll():self { + $this->select = []; + $this->selectAllExcept = []; return $this; } + /** @deprecated Use selectAll() instead to avoid ambiguity with immutable `with` functions */ + public function withAll():self { + return $this->selectAll(); + } public function setTrigger(string $key, string $value):self { if(!isset($this->matches[$key])) { @@ -85,13 +102,13 @@ protected function setKeyTrigger(string $key):self { return $this; } - public function call(callable $callback, ...$args):self { + public function call(callable $callback, string...$args):self { $this->callbacks []= new Callback($callback, ...$args); $this->hasFired = $this->fire(); return $this; } - public function or(callable $callback, ...$args):self { + public function orCall(callable $callback, string...$args):self { if(is_null($this->hasFired)) { throw new CallOrOutOfSequenceException(); } @@ -134,11 +151,11 @@ public function fire():bool { return $fired; } - protected function callCallbacks() { - $fields = InputDataFactory::create( + protected function callCallbacks():void { + $fields = $this->inputDataFactory->create( $this->input, - $this->with, - $this->without + $this->select, + $this->selectAllExcept ); foreach($this->callbacks as $callback) { @@ -147,6 +164,10 @@ protected function callCallbacks() { } } + /** + * @param array> $array + * @return array + */ protected function flattenArray(array $array):array { $result = []; @@ -179,4 +200,4 @@ protected function flattenArray(array $array):array { return $result; } -} \ No newline at end of file +} diff --git a/src/UploadedFileMoveException.php b/src/UploadedFileMoveException.php index a44c9d4..46cfee2 100644 --- a/src/UploadedFileMoveException.php +++ b/src/UploadedFileMoveException.php @@ -1,4 +1,4 @@ ["Mozzarella", "Basil", "Mushroom", "Peppers", "Onion", "Spinach"], + "name" => "Greg's pizza", + ]; + } + public static function getRandomKvp(int $num, string $prefix = ""):array { $kvp = []; @@ -103,4 +110,4 @@ public static function getTestDirectory() { "test", ]); } -} \ No newline at end of file +} diff --git a/test/phpunit/Helper/Reflection.php b/test/phpunit/Helper/Reflection.php index c04760c..6c98efc 100644 --- a/test/phpunit/Helper/Reflection.php +++ b/test/phpunit/Helper/Reflection.php @@ -11,4 +11,4 @@ public static function getMethod(string $className, string $methodName):Reflecti $method->setAccessible(true); return $method; } -} \ No newline at end of file +} diff --git a/test/phpunit/InputData/BodyInputDataTest.php b/test/phpunit/InputData/BodyInputDataTest.php new file mode 100644 index 0000000..bfe4f0e --- /dev/null +++ b/test/phpunit/InputData/BodyInputDataTest.php @@ -0,0 +1,18 @@ +get("name")); + self::assertInstanceOf(MultipleInputDatum::class, $sut->get("toppings")); + self::assertNull($sut->get("nothing")); + } +} diff --git a/test/phpunit/InputData/FileUploadInputDataTest.php b/test/phpunit/InputData/FileUploadInputDataTest.php index 9af48df..98c10c2 100644 --- a/test/phpunit/InputData/FileUploadInputDataTest.php +++ b/test/phpunit/InputData/FileUploadInputDataTest.php @@ -1,5 +1,5 @@ createInput(); - $data = InputDataFactory::create($input); - self::assertEquals("Edward", $data["name"]); - self::assertEquals("51", $data["age"]); - self::assertEquals("01234 567890", $data["telephone"]); - self::assertEquals("AB12 3CD", $data["postcode"]); + $inputDataFactory = new InputDataFactory(); + $data = $inputDataFactory->create($input); + self::assertSame("Edward", (string)$data["name"]); + self::assertSame("51", (string)$data["age"]); + self::assertSame("01234 567890", (string)$data["telephone"]); + self::assertSame("AB12 3CD", (string)$data["postcode"]); } - public function testCreateCriteriaWith():void { + public function testCreateCriteriaWith(): void { $input = $this->createInput(); - $data = InputDataFactory::create($input, ["name", "postcode"]); - self::assertEquals("Edward", $data["name"]); + $inputDataFactory = new InputDataFactory(); + $data = $inputDataFactory->create($input, ["name", "postcode"]); + self::assertSame("Edward", (string)$data["name"]); self::assertNull($data["age"]); self::assertNull($data["telephone"]); - self::assertEquals("AB12 3CD", $data["postcode"]); + self::assertSame("AB12 3CD", (string)$data["postcode"]); } - public function testCreateCriteriaWithout():void { + public function testCreateCriteriaWithout(): void { $input = $this->createInput(); - $data = InputDataFactory::create($input, [],["age", "telephone"]); - self::assertEquals("Edward", $data["name"]); + $inputDataFactory = new InputDataFactory(); + $data = $inputDataFactory->create($input, [], ["age", "telephone"]); + self::assertSame("Edward", (string)$data["name"]); self::assertNull($data["age"]); self::assertNull($data["telephone"]); - self::assertEquals("AB12 3CD", $data["postcode"]); + self::assertSame("AB12 3CD", (string)$data["postcode"]); } - public function testCreateCriteriaWithWithoutNoClash():void { + public function testCreateCriteriaWithWithoutNoClash(): void { $input = $this->createInput(); - $data = InputDataFactory::create($input, ["name"], ["postcode"]); - self::assertEquals("Edward", $data["name"]); + $inputDataFactory = new InputDataFactory(); + $data = $inputDataFactory->create($input, ["name"], ["postcode"]); + self::assertSame("Edward", (string)$data["name"]); self::assertNull($data["age"]); self::assertNull($data["telephone"]); self::assertNull($data["postcode"]); } - public function testCreateCriteriaWithWithoutClash():void { + public function testCreateCriteriaWithWithoutClash(): void { $input = $this->createInput(); self::expectException(WithWithoutClashingException::class); - InputDataFactory::create($input, ["name", "age"], ["age"]); + $inputDataFactory = new InputDataFactory(); + $inputDataFactory->create($input, ["name", "age"], ["age"]); } - protected function createInput() { + protected function createInput(): Input { return new Input([ - "name" => "Edward", - "age" => 51, - "telephone" => "01234 567890", - "postcode" => "AB12 3CD", + "name" => "Edward", + "age" => 51, + "telephone" => "01234 567890", + "postcode" => "AB12 3CD", ]); } -} \ No newline at end of file +} diff --git a/test/phpunit/InputData/InputDataTest.php b/test/phpunit/InputData/InputDataTest.php index 08ac302..9e0d924 100644 --- a/test/phpunit/InputData/InputDataTest.php +++ b/test/phpunit/InputData/InputDataTest.php @@ -1,6 +1,6 @@ "Alice", "gender" => "f", ]); - self::assertEquals("Alice", $data["name"]); - self::assertEquals("f", $data["gender"]); + self::assertSame("Alice", (string)$data["name"]); + self::assertSame("f", (string)$data["gender"]); } public function testMultipleSources():void { @@ -24,24 +24,24 @@ public function testMultipleSources():void { "userAccess" => "admin", ]); - self::assertEquals("Alice", $data["name"]); - self::assertEquals("f", $data["gender"]); - self::assertEquals("save", $data["do"]); - self::assertEquals("admin", $data["userAccess"]); + self::assertSame("Alice", (string)$data["name"]); + self::assertSame("f", (string)$data["gender"]); + self::assertSame("save", (string)$data["do"]); + self::assertSame("admin", (string)$data["userAccess"]); } public function testAddFromEmpty():void { $data = new InputData(); $data->addKeyValue("name", "Bob"); - self::assertEquals("Bob", $data["name"]); + self::assertSame("Bob", (string)$data["name"]); } public function testAddMultipleFromEmpty():void { $data = new InputData(); $data->addKeyValue("name", "Bob"); $data->addKeyValue("gender", "m"); - self::assertEquals("Bob", $data["name"]); - self::assertEquals("m", $data["gender"]); + self::assertSame("Bob", (string)$data["name"]); + self::assertSame("m", (string)$data["gender"]); } public function testAddFromExisting():void { @@ -56,12 +56,12 @@ public function testAddFromExisting():void { $data->addKeyValue("view", "tab1"); $data->addKeyValue("screenSize", "large"); - self::assertEquals("Charles", $data["name"]); - self::assertEquals("m", $data["gender"]); - self::assertEquals("save", $data["do"]); - self::assertEquals("admin", $data["userAccess"]); - self::assertEquals("tab1", $data["view"]); - self::assertEquals("large", $data["screenSize"]); + self::assertSame("Charles", (string)$data["name"]); + self::assertSame("m", (string)$data["gender"]); + self::assertSame("save", (string)$data["do"]); + self::assertSame("admin", (string)$data["userAccess"]); + self::assertSame("tab1", (string)$data["view"]); + self::assertSame("large", (string)$data["screenSize"]); } public function testRemove():void { @@ -70,7 +70,7 @@ public function testRemove():void { "gender" => "f", ]); - self::assertEquals("f", $data["gender"]); + self::assertSame("f", (string)$data["gender"]); $data->remove("gender"); self::assertNull($data["gender"]); } @@ -96,7 +96,7 @@ public function testRemoveExceptSingle():void { $data->removeExcept("userAccess"); self::assertNull($data["name"]); self::assertNull($data["gender"]); - self::assertEquals("sales", $data["userAccess"]); + self::assertSame("sales", (string)$data["userAccess"]); } public function testRemoveExceptMulti():void { @@ -106,8 +106,8 @@ public function testRemoveExceptMulti():void { "userAccess" => "sales", ]); $data->removeExcept("name", "userAccess"); - self::assertEquals("Emma", $data["name"]); - self::assertEquals("sales", $data["userAccess"]); + self::assertSame("Emma", (string)$data["name"]); + self::assertSame("sales", (string)$data["userAccess"]); self::assertNull($data["gender"]); } @@ -128,9 +128,9 @@ public function testSetAsArray():void { "gender" => "f", ]); $data["userAccess"] = "test"; - self::assertEquals("Hannah", $data["name"]); - self::assertEquals("f", $data["gender"]); - self::assertEquals("test", $data["userAccess"]); + self::assertSame("Hannah", (string)$data["name"]); + self::assertSame("f", (string)$data["gender"]); + self::assertSame("test", (string)$data["userAccess"]); } public function testUnsetAsArray():void { @@ -141,7 +141,7 @@ public function testUnsetAsArray():void { self::assertTrue(isset($data["gender"])); unset($data["gender"]); self::assertFalse(isset($data["gender"])); - self::assertEquals("Ian", $data["name"]); + self::assertSame("Ian", (string)$data["name"]); } public function testHas():void { @@ -205,4 +205,4 @@ public function testToArrayWithMultipleInputDatum():void { } } } -} \ No newline at end of file +} diff --git a/test/phpunit/InputTest.php b/test/phpunit/InputTest.php index 50f507b..9ae0989 100644 --- a/test/phpunit/InputTest.php +++ b/test/phpunit/InputTest.php @@ -5,11 +5,15 @@ use Gt\Input\DataNotCompatibleFormatException; use Gt\Input\Input; use Gt\Input\InputData\Datum\FileUpload; +use Gt\Input\InputData\Datum\InputDatum; use Gt\Input\InputData\InputData; use Gt\Input\InvalidInputMethodException; use Gt\Input\MissingInputParameterException; use Gt\Input\Test\Helper\Helper; use Gt\Input\Trigger\Trigger; +use Gt\Json\JsonObject; +use Gt\Json\JsonPrimitive\JsonArrayPrimitive; +use Gt\Json\JsonPrimitive\JsonStringPrimitive; use PHPUnit\Framework\TestCase; class InputTest extends TestCase { @@ -120,6 +124,12 @@ public function testGetFileFieldSingle(array $get, array $post):void { ); } + public function testGetFile_null():void { + $input = new Input([], [], []); + $file = $input->getFile("exampleFile"); + self::assertNull($file); + } + /** @dataProvider dataRandomGetPost */ public function testGetInvalidDataType(array $get, array $post):void { self::expectException(InvalidInputMethodException::class); @@ -632,7 +642,99 @@ public function testContainsThrowsExceptionOnIncorrectType($get, $post) { $input->contains("anything", "invalid-method"); } - public function dataRandomGetPost():array { + public function testGetMultipleFile():void { + $get = []; + $post = ["do" => "upload"]; + $files = [ + "uploads" => [ + "name" => ["one.txt", "two.txt"], + "type" => ["plain/text", "plain/text"], + "size" => [123, 321], + "tmp_name" => ["/tmp/aaaaa", "/tmp/bbbbb"], + "error" => [0, 0], + "full_path" => ["one.txt", "two.txt"], + ] + ]; + $sut = new Input($get, $post, $files); + $multipleFiles = $sut->getMultipleFile("uploads"); + self::assertCount(count($files["uploads"]["name"]), $multipleFiles); + + $i = 0; + foreach($multipleFiles as $fileName => $file) { + self::assertSame($files["uploads"]["name"][$i], $fileName); + self::assertSame($files["uploads"]["tmp_name"][$i], $file->getRealPath()); + $i++; + } + } + + public function testGetBodyJson_notJson():void { + $get = []; + $post = ["this" => "is not JSON!"]; + $sut = new Input($get, $post); + $json = $sut->getBodyJson(); + self::assertNull($json); + } + + public function testGetBodyJson_string():void { + $inputPath = tempnam(sys_get_temp_dir(), "phpgt-input-test-"); + file_put_contents($inputPath, "\"Hello, PHP.Gt!\""); + $sut = new Input(bodyPath: $inputPath); + $json = $sut->getBodyJson(); + self::assertInstanceOf(JsonStringPrimitive::class, $json); + self::assertSame("Hello, PHP.Gt!", $json->getPrimitiveValue()); + } + + public function testGetBodyJson_arrayWithObject():void { + $inputPath = tempnam(sys_get_temp_dir(), "phpgt-input-test-"); + file_put_contents($inputPath, "[1, 2, 3, {\"name\": \"Cody\"}]"); + $sut = new Input(bodyPath: $inputPath); + $json = $sut->getBodyJson(); + self::assertInstanceOf(JsonArrayPrimitive::class, $json); + $array = $json->getPrimitiveValue(); + self::assertSame(1, $array[0]); + self::assertSame(2, $array[1]); + self::assertSame(3, $array[2]); + /** @var JsonObject $thirdArrayElement */ + $thirdArrayElement = $array[3]; + self::assertInstanceOf(JsonObject::class, $thirdArrayElement); + self::assertSame("Cody", $thirdArrayElement->getString("name")); + } + + public function testGetBodyJson_withQueryString():void { + $inputPath = tempnam(sys_get_temp_dir(), "phpgt-input-test-"); + file_put_contents($inputPath, "\"Hello, PHP.Gt!\""); + $sut = new Input(["id" => 123], bodyPath: $inputPath); + $json = $sut->getBodyJson(); + self::assertInstanceOf(JsonStringPrimitive::class, $json); + self::assertSame("Hello, PHP.Gt!", $json->getPrimitiveValue()); + self::assertSame(123, $sut->getInt("id")); + } + + public function testSelectPrefix_noMatch():void { + $sut = new Input(["id" => 123]); + $trigger = $sut->selectPrefix("io_"); + + $triggered = false; + $trigger->call(function(...$args)use(&$triggered) { + $triggered = true; + }); + $trigger->fire(); + self::assertFalse($triggered); + } + + public function testSelectPrefix_match():void { + $sut = new Input(["id" => 123, "io_database" => "connect"]); + $trigger = $sut->selectPrefix("io_"); + + $triggered = false; + $trigger->call(function(...$args)use(&$triggered) { + $triggered = true; + }); + $trigger->fire(); + self::assertTrue($triggered); + } + + public static function dataRandomGetPost():array { $data = []; for($i = 0; $i < 10; $i++) { @@ -646,7 +748,7 @@ public function dataRandomGetPost():array { return $data; } - public function dataRandomString():array { + public static function dataRandomString():array { $data = []; for($i = 0; $i < 10; $i++) { @@ -658,4 +760,4 @@ public function dataRandomString():array { return $data; } -} \ No newline at end of file +} diff --git a/test/phpunit/Trigger/CallbackTest.php b/test/phpunit/Trigger/CallbackTest.php index c8642a4..e3a1abd 100644 --- a/test/phpunit/Trigger/CallbackTest.php +++ b/test/phpunit/Trigger/CallbackTest.php @@ -1,5 +1,5 @@ fire()); } + public function testWhenWithKVP_missing():void { + $sut = new Trigger(new Input([ + "name" => "Cody", + "colour" => "orange", + ])); + $sut->when([ + "colour" => "white", + ]); + self::assertFalse($sut->fire()); + } + + public function testWhenWithKVP():void { + $sut = new Trigger(new Input([ + "name" => "Cody", + "colour" => "orange", + ])); + $sut->when([ + "colour" => "orange", + ]); + self::assertTrue($sut->fire()); + } + /** @dataProvider dataInput */ public function testWithSingleKey(Input $input):void { $keys = Helper::getKeysFromInput($input, 1); @@ -44,7 +66,6 @@ public function testWithSingleKey(Input $input):void { /** @dataProvider dataInput */ public function testFiresOr(Input $input):void { - $keys = Helper::getKeysFromInput($input, 1); $trigger = new Trigger($input); $trigger->when("this-does-not-exist"); $callbackCount = 0; @@ -53,7 +74,7 @@ public function testFiresOr(Input $input):void { $trigger->call(function() use(&$callbackCount) { $callbackCount++; }); - $trigger->or(function() use(&$orCount) { + $trigger->orCall(function() use(&$orCount) { $orCount++; }); @@ -66,7 +87,7 @@ public function testExceptionOrThrown(Input $input):void { self::expectException(CallOrOutOfSequenceException::class); $trigger = new Trigger($input); $trigger->when("this-does-not-exist"); - $trigger->or(function() use(&$orCount) { + $trigger->orCall(function() use(&$orCount) { $orCount++; }); } @@ -248,7 +269,7 @@ public function testFiresWithNoMatches(Input $input):void { self::assertTrue($trigger->fire()); } - public function dataInput():array { + public static function dataInput():array { $data = []; for($i = 0; $i < 10; $i++) { @@ -261,4 +282,4 @@ public function dataInput():array { return $data; } -} \ No newline at end of file +} diff --git a/test/phpunit/phpunit.xml b/test/phpunit/phpunit.xml deleted file mode 100644 index cf95bea..0000000 --- a/test/phpunit/phpunit.xml +++ /dev/null @@ -1,18 +0,0 @@ - - - - - ../../src - - - - - - - - - . - - - - \ No newline at end of file