├── .php-cs-fixer.php ├── CHANGELOG.md ├── LICENSE ├── README.md ├── composer.json ├── src ├── Assert.php ├── InvalidArgumentException.php └── Mixin.php └── tools ├── php-cs-fixer ├── composer.json └── composer.lock ├── phpunit ├── composer.json └── composer.lock ├── psalm ├── composer.json └── composer.lock └── roave-bc-check ├── composer.json └── composer.lock /.php-cs-fixer.php: -------------------------------------------------------------------------------- 1 | in(__DIR__.'/src') 5 | ->in(__DIR__.'/tests') 6 | ; 7 | 8 | return (new PhpCsFixer\Config()) 9 | ->setRiskyAllowed(true) 10 | ->setRules([ 11 | '@PSR2' => true, 12 | '@Symfony' => true, 13 | 'ordered_imports' => true, 14 | 'array_syntax' => ['syntax' => 'long'], 15 | 'fully_qualified_strict_types' => false, 16 | 'global_namespace_import' => true, 17 | 'no_superfluous_phpdoc_tags' => false, 18 | 'phpdoc_annotation_without_dot' => false, 19 | 'phpdoc_types_order' => false, 20 | 'phpdoc_separation' => ['skip_unlisted_annotations' => true], 21 | 'phpdoc_summary' => false, 22 | 'phpdoc_to_comment' => false, 23 | 'phpdoc_align' => false, 24 | 'yoda_style' => false, 25 | ]) 26 | ->setFinder($finder) 27 | ; 28 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | Changelog 2 | ========= 3 | 4 | ## UNRELEASED 5 | 6 | ### Fixed 7 | 8 | - Corrected messages and typos in various assertions 9 | 10 | ## 1.11.0 11 | 12 | ### Added 13 | 14 | * Added explicit (non-magic) `allNullOr*` methods, with `@psalm-assert` annotations, for better Psalm support. 15 | 16 | ### Changed 17 | 18 | * Trait methods will now check the assertion themselves, instead of using `__callStatic` 19 | * `isList` will now deal correctly with (modified) lists that contain `NaN` 20 | * `reportInvalidArgument` now has a return type of `never`. 21 | 22 | ### Removed 23 | 24 | * Removed `symfony/polyfill-ctype` as a dependency, and require `ext-ctype` instead. 25 | * You can still require the `symfony/polyfill-ctype` in your project if you need it, as it provides `ext-ctype` 26 | 27 | ## 1.10.0 28 | 29 | ### Added 30 | 31 | * On invalid assertion, we throw a `Webmozart\Assert\InvalidArgumentException` 32 | * Added `Assert::positiveInteger()` 33 | 34 | ### Changed 35 | 36 | * Using a trait with real implementations of `all*()` and `nullOr*()` methods to improve psalm compatibility. 37 | 38 | ### Removed 39 | 40 | * Support for PHP <7.2 41 | 42 | ## 1.9.1 43 | 44 | ## Fixed 45 | 46 | * provisional support for PHP 8.0 47 | 48 | ## 1.9.0 49 | 50 | * added better Psalm support for `all*` & `nullOr*` methods 51 | * These methods are now understood by Psalm through a mixin. You may need a newer version of Psalm in order to use this 52 | * added `@psalm-pure` annotation to `Assert::notFalse()` 53 | * added more `@psalm-assert` annotations where appropriate 54 | 55 | ## Changed 56 | 57 | * the `all*` & `nullOr*` methods are now declared on an interface, instead of `@method` annotations. 58 | This interface is linked to the `Assert` class with a `@mixin` annotation. Most IDEs have supported this 59 | for a long time, and you should not lose any autocompletion capabilities. PHPStan has supported this since 60 | version `0.12.20`. This package is marked incompatible (with a composer conflict) with phpstan version prior to that. 61 | If you do not use PHPStan than this does not matter. 62 | 63 | ## 1.8.0 64 | 65 | ### Added 66 | 67 | * added `Assert::notStartsWith()` 68 | * added `Assert::notEndsWith()` 69 | * added `Assert::inArray()` 70 | * added `@psalm-pure` annotations to pure assertions 71 | 72 | ### Fixed 73 | 74 | * Exception messages of comparisons between `DateTime(Immutable)` objects now display their date & time. 75 | * Custom Exception messages for `Assert::count()` now use the values to render the exception message. 76 | 77 | ## 1.7.0 (2020-02-14) 78 | 79 | ### Added 80 | 81 | * added `Assert::notFalse()` 82 | * added `Assert::isAOf()` 83 | * added `Assert::isAnyOf()` 84 | * added `Assert::isNotA()` 85 | 86 | ## 1.6.0 (2019-11-24) 87 | 88 | ### Added 89 | 90 | * added `Assert::validArrayKey()` 91 | * added `Assert::isNonEmptyList()` 92 | * added `Assert::isNonEmptyMap()` 93 | * added `@throws InvalidArgumentException` annotations to all methods that throw. 94 | * added `@psalm-assert` for the list type to the `isList` assertion. 95 | 96 | ### Fixed 97 | 98 | * `ResourceBundle` & `SimpleXMLElement` now pass the `isCountable` assertions. 99 | They are countable, without implementing the `Countable` interface. 100 | * The doc block of `range` now has the proper variables. 101 | * An empty array will now pass `isList` and `isMap`. As it is a valid form of both. 102 | If a non-empty variant is needed, use `isNonEmptyList` or `isNonEmptyMap`. 103 | 104 | ### Changed 105 | 106 | * Removed some `@psalm-assert` annotations, that were 'side effect' assertions See: 107 | * [#144](https://github.com/webmozart/assert/pull/144) 108 | * [#145](https://github.com/webmozart/assert/issues/145) 109 | * [#146](https://github.com/webmozart/assert/pull/146) 110 | * [#150](https://github.com/webmozart/assert/pull/150) 111 | * If you use Psalm, the minimum version needed is `3.6.0`. Which is enforced through a composer conflict. 112 | If you don't use Psalm, then this has no impact. 113 | 114 | ## 1.5.0 (2019-08-24) 115 | 116 | ### Added 117 | 118 | * added `Assert::uniqueValues()` 119 | * added `Assert::unicodeLetters()` 120 | * added: `Assert::email()` 121 | * added support for [Psalm](https://github.com/vimeo/psalm), by adding `@psalm-assert` annotations where appropriate. 122 | 123 | ### Fixed 124 | 125 | * `Assert::endsWith()` would not give the correct result when dealing with a multibyte suffix. 126 | * `Assert::length(), minLength, maxLength, lengthBetween` would not give the correct result when dealing with multibyte characters. 127 | 128 | **NOTE**: These 2 changes may break your assertions if you relied on the fact that multibyte characters didn't behave correctly. 129 | 130 | ### Changed 131 | 132 | * The names of some variables have been updated to better reflect what they are. 133 | * All function calls are now in their FQN form, slightly increasing performance. 134 | * Tests are now properly ran against HHVM-3.30 and PHP nightly. 135 | 136 | ### Deprecation 137 | 138 | * deprecated `Assert::isTraversable()` in favor of `Assert::isIterable()` 139 | * This was already done in 1.3.0, but it was only done through a silenced `trigger_error`. It is now annotated as well. 140 | 141 | ## 1.4.0 (2018-12-25) 142 | 143 | ### Added 144 | 145 | * added `Assert::ip()` 146 | * added `Assert::ipv4()` 147 | * added `Assert::ipv6()` 148 | * added `Assert::notRegex()` 149 | * added `Assert::interfaceExists()` 150 | * added `Assert::isList()` 151 | * added `Assert::isMap()` 152 | * added polyfill for ctype 153 | 154 | ### Fixed 155 | 156 | * Special case when comparing objects implementing `__toString()` 157 | 158 | ## 1.3.0 (2018-01-29) 159 | 160 | ### Added 161 | 162 | * added `Assert::minCount()` 163 | * added `Assert::maxCount()` 164 | * added `Assert::countBetween()` 165 | * added `Assert::isCountable()` 166 | * added `Assert::notWhitespaceOnly()` 167 | * added `Assert::natural()` 168 | * added `Assert::notContains()` 169 | * added `Assert::isArrayAccessible()` 170 | * added `Assert::isInstanceOfAny()` 171 | * added `Assert::isIterable()` 172 | 173 | ### Fixed 174 | 175 | * `stringNotEmpty` will no longer report "0" is an empty string 176 | 177 | ### Deprecation 178 | 179 | * deprecated `Assert::isTraversable()` in favor of `Assert::isIterable()` 180 | 181 | ## 1.2.0 (2016-11-23) 182 | 183 | * added `Assert::throws()` 184 | * added `Assert::count()` 185 | * added extension point `Assert::reportInvalidArgument()` for custom subclasses 186 | 187 | ## 1.1.0 (2016-08-09) 188 | 189 | * added `Assert::object()` 190 | * added `Assert::propertyExists()` 191 | * added `Assert::propertyNotExists()` 192 | * added `Assert::methodExists()` 193 | * added `Assert::methodNotExists()` 194 | * added `Assert::uuid()` 195 | 196 | ## 1.0.2 (2015-08-24) 197 | 198 | * integrated Style CI 199 | * add tests for minimum package dependencies on Travis CI 200 | 201 | ## 1.0.1 (2015-05-12) 202 | 203 | * added support for PHP 5.3.3 204 | 205 | ## 1.0.0 (2015-05-12) 206 | 207 | * first stable release 208 | 209 | ## 1.0.0-beta (2015-03-19) 210 | 211 | * first beta release 212 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2014 Bernhard Schussek 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of 6 | this software and associated documentation files (the "Software"), to deal in 7 | the Software without restriction, including without limitation the rights to 8 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 9 | the Software, and to permit persons to whom the Software is furnished to do so, 10 | subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 17 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 18 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 19 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 20 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Webmozart Assert 2 | ================ 3 | 4 | [![Latest Stable Version](https://poser.pugx.org/webmozart/assert/v/stable.svg)](https://packagist.org/packages/webmozart/assert) 5 | [![Total Downloads](https://poser.pugx.org/webmozart/assert/downloads.svg)](https://packagist.org/packages/webmozart/assert) 6 | 7 | This library contains efficient assertions to test the input and output of 8 | your methods. With these assertions, you can greatly reduce the amount of coding 9 | needed to write a safe implementation. 10 | 11 | All assertions in the [`Assert`] class throw an `Webmozart\Assert\InvalidArgumentException` if 12 | they fail. 13 | 14 | FAQ 15 | --- 16 | 17 | **What's the difference to [beberlei/assert]?** 18 | 19 | This library is heavily inspired by Benjamin Eberlei's wonderful [assert package], 20 | but fixes a usability issue with error messages that can't be fixed there without 21 | breaking backwards compatibility. 22 | 23 | This package features usable error messages by default. However, you can also 24 | easily write custom error messages: 25 | 26 | ``` 27 | Assert::string($path, 'The path is expected to be a string. Got: %s'); 28 | ``` 29 | 30 | In [beberlei/assert], the ordering of the `%s` placeholders is different for 31 | every assertion. This package, on the contrary, provides consistent placeholder 32 | ordering for all assertions: 33 | 34 | * `%s`: The tested value as string, e.g. `"/foo/bar"`. 35 | * `%2$s`, `%3$s`, ...: Additional assertion-specific values, e.g. the 36 | minimum/maximum length, allowed values, etc. 37 | 38 | Check the source code of the assertions to find out details about the additional 39 | available placeholders. 40 | 41 | Installation 42 | ------------ 43 | 44 | Use [Composer] to install the package: 45 | 46 | ```bash 47 | composer require webmozart/assert 48 | ``` 49 | 50 | Example 51 | ------- 52 | 53 | ```php 54 | use Webmozart\Assert\Assert; 55 | 56 | class Employee 57 | { 58 | public function __construct($id) 59 | { 60 | Assert::integer($id, 'The employee ID must be an integer. Got: %s'); 61 | Assert::greaterThan($id, 0, 'The employee ID must be a positive integer. Got: %s'); 62 | } 63 | } 64 | ``` 65 | 66 | If you create an employee with an invalid ID, an exception is thrown: 67 | 68 | ```php 69 | new Employee('foobar'); 70 | // => Webmozart\Assert\InvalidArgumentException: 71 | // The employee ID must be an integer. Got: string 72 | 73 | new Employee(-10); 74 | // => Webmozart\Assert\InvalidArgumentException: 75 | // The employee ID must be a positive integer. Got: -10 76 | ``` 77 | 78 | Assertions 79 | ---------- 80 | 81 | The [`Assert`] class provides the following assertions: 82 | 83 | ### Type Assertions 84 | 85 | Method | Description 86 | -------------------------------------------------------- | -------------------------------------------------- 87 | `string($value, $message = '')` | Check that a value is a string 88 | `stringNotEmpty($value, $message = '')` | Check that a value is a non-empty string 89 | `integer($value, $message = '')` | Check that a value is an integer 90 | `integerish($value, $message = '')` | Check that a value casts to an integer 91 | `positiveInteger($value, $message = '')` | Check that a value is a positive (non-zero) integer 92 | `float($value, $message = '')` | Check that a value is a float 93 | `numeric($value, $message = '')` | Check that a value is numeric 94 | `natural($value, $message = '')` | Check that a value is a non-negative integer 95 | `boolean($value, $message = '')` | Check that a value is a boolean 96 | `scalar($value, $message = '')` | Check that a value is a scalar 97 | `object($value, $message = '')` | Check that a value is an object 98 | `resource($value, $type = null, $message = '')` | Check that a value is a resource 99 | `isCallable($value, $message = '')` | Check that a value is a callable 100 | `isArray($value, $message = '')` | Check that a value is an array 101 | `isTraversable($value, $message = '')` (deprecated) | Check that a value is an array or a `\Traversable` 102 | `isIterable($value, $message = '')` | Check that a value is an array or a `\Traversable` 103 | `isCountable($value, $message = '')` | Check that a value is an array or a `\Countable` 104 | `isInstanceOf($value, $class, $message = '')` | Check that a value is an `instanceof` a class 105 | `isInstanceOfAny($value, array $classes, $message = '')` | Check that a value is an `instanceof` at least one class on the array of classes 106 | `notInstanceOf($value, $class, $message = '')` | Check that a value is not an `instanceof` a class 107 | `isAOf($value, $class, $message = '')` | Check that a value is of the class or has one of its parents 108 | `isAnyOf($value, array $classes, $message = '')` | Check that a value is of at least one of the classes or has one of its parents 109 | `isNotA($value, $class, $message = '')` | Check that a value is not of the class or has not one of its parents 110 | `isArrayAccessible($value, $message = '')` | Check that a value can be accessed as an array 111 | `uniqueValues($values, $message = '')` | Check that the given array contains unique values 112 | 113 | ### Comparison Assertions 114 | 115 | Method | Description 116 | ----------------------------------------------- | ------------------------------------------------------------------ 117 | `true($value, $message = '')` | Check that a value is `true` 118 | `false($value, $message = '')` | Check that a value is `false` 119 | `notFalse($value, $message = '')` | Check that a value is not `false` 120 | `null($value, $message = '')` | Check that a value is `null` 121 | `notNull($value, $message = '')` | Check that a value is not `null` 122 | `isEmpty($value, $message = '')` | Check that a value is `empty()` 123 | `notEmpty($value, $message = '')` | Check that a value is not `empty()` 124 | `eq($value, $value2, $message = '')` | Check that a value equals another (`==`) 125 | `notEq($value, $value2, $message = '')` | Check that a value does not equal another (`!=`) 126 | `same($value, $value2, $message = '')` | Check that a value is identical to another (`===`) 127 | `notSame($value, $value2, $message = '')` | Check that a value is not identical to another (`!==`) 128 | `greaterThan($value, $value2, $message = '')` | Check that a value is greater than another 129 | `greaterThanEq($value, $value2, $message = '')` | Check that a value is greater than or equal to another 130 | `lessThan($value, $value2, $message = '')` | Check that a value is less than another 131 | `lessThanEq($value, $value2, $message = '')` | Check that a value is less than or equal to another 132 | `range($value, $min, $max, $message = '')` | Check that a value is within a range 133 | `inArray($value, array $values, $message = '')` | Check that a value is one of a list of values 134 | `oneOf($value, array $values, $message = '')` | Check that a value is one of a list of values (alias of `inArray`) 135 | 136 | ### String Assertions 137 | 138 | You should check that a value is a string with `Assert::string()` before making 139 | any of the following assertions. 140 | 141 | Method | Description 142 | --------------------------------------------------- | ----------------------------------------------------------------- 143 | `contains($value, $subString, $message = '')` | Check that a string contains a substring 144 | `notContains($value, $subString, $message = '')` | Check that a string does not contain a substring 145 | `startsWith($value, $prefix, $message = '')` | Check that a string has a prefix 146 | `notStartsWith($value, $prefix, $message = '')` | Check that a string does not have a prefix 147 | `startsWithLetter($value, $message = '')` | Check that a string starts with a letter 148 | `endsWith($value, $suffix, $message = '')` | Check that a string has a suffix 149 | `notEndsWith($value, $suffix, $message = '')` | Check that a string does not have a suffix 150 | `regex($value, $pattern, $message = '')` | Check that a string matches a regular expression 151 | `notRegex($value, $pattern, $message = '')` | Check that a string does not match a regular expression 152 | `unicodeLetters($value, $message = '')` | Check that a string contains Unicode letters only 153 | `alpha($value, $message = '')` | Check that a string contains letters only 154 | `digits($value, $message = '')` | Check that a string contains digits only 155 | `alnum($value, $message = '')` | Check that a string contains letters and digits only 156 | `lower($value, $message = '')` | Check that a string contains lowercase characters only 157 | `upper($value, $message = '')` | Check that a string contains uppercase characters only 158 | `length($value, $length, $message = '')` | Check that a string has a certain number of characters 159 | `minLength($value, $min, $message = '')` | Check that a string has at least a certain number of characters 160 | `maxLength($value, $max, $message = '')` | Check that a string has at most a certain number of characters 161 | `lengthBetween($value, $min, $max, $message = '')` | Check that a string has a length in the given range 162 | `uuid($value, $message = '')` | Check that a string is a valid UUID 163 | `ip($value, $message = '')` | Check that a string is a valid IP (either IPv4 or IPv6) 164 | `ipv4($value, $message = '')` | Check that a string is a valid IPv4 165 | `ipv6($value, $message = '')` | Check that a string is a valid IPv6 166 | `email($value, $message = '')` | Check that a string is a valid e-mail address 167 | `notWhitespaceOnly($value, $message = '')` | Check that a string contains at least one non-whitespace character 168 | 169 | ### File Assertions 170 | 171 | Method | Description 172 | ----------------------------------- | -------------------------------------------------- 173 | `fileExists($value, $message = '')` | Check that a value is an existing path 174 | `file($value, $message = '')` | Check that a value is an existing file 175 | `directory($value, $message = '')` | Check that a value is an existing directory 176 | `readable($value, $message = '')` | Check that a value is a readable path 177 | `writable($value, $message = '')` | Check that a value is a writable path 178 | 179 | ### Object Assertions 180 | 181 | Method | Description 182 | ----------------------------------------------------- | -------------------------------------------------- 183 | `classExists($value, $message = '')` | Check that a value is an existing class name 184 | `subclassOf($value, $class, $message = '')` | Check that a class is a subclass of another 185 | `interfaceExists($value, $message = '')` | Check that a value is an existing interface name 186 | `implementsInterface($value, $class, $message = '')` | Check that a class implements an interface 187 | `propertyExists($value, $property, $message = '')` | Check that a property exists in a class/object 188 | `propertyNotExists($value, $property, $message = '')` | Check that a property does not exist in a class/object 189 | `methodExists($value, $method, $message = '')` | Check that a method exists in a class/object 190 | `methodNotExists($value, $method, $message = '')` | Check that a method does not exist in a class/object 191 | 192 | ### Array Assertions 193 | 194 | Method | Description 195 | -------------------------------------------------- | ------------------------------------------------------------------ 196 | `keyExists($array, $key, $message = '')` | Check that a key exists in an array 197 | `keyNotExists($array, $key, $message = '')` | Check that a key does not exist in an array 198 | `validArrayKey($key, $message = '')` | Check that a value is a valid array key (int or string) 199 | `count($array, $number, $message = '')` | Check that an array contains a specific number of elements 200 | `minCount($array, $min, $message = '')` | Check that an array contains at least a certain number of elements 201 | `maxCount($array, $max, $message = '')` | Check that an array contains at most a certain number of elements 202 | `countBetween($array, $min, $max, $message = '')` | Check that an array has a count in the given range 203 | `isList($array, $message = '')` | Check that an array is a non-associative list 204 | `isNonEmptyList($array, $message = '')` | Check that an array is a non-associative list, and not empty 205 | `isMap($array, $message = '')` | Check that an array is associative and has strings as keys 206 | `isNonEmptyMap($array, $message = '')` | Check that an array is associative and has strings as keys, and is not empty 207 | 208 | ### Function Assertions 209 | 210 | Method | Description 211 | ------------------------------------------- | ----------------------------------------------------------------------------------------------------- 212 | `throws($closure, $class, $message = '')` | Check that a function throws a certain exception. Subclasses of the exception class will be accepted. 213 | 214 | ### Collection Assertions 215 | 216 | All of the above assertions can be prefixed with `all*()` to test the contents 217 | of an array or a `\Traversable`: 218 | 219 | ```php 220 | Assert::allIsInstanceOf($employees, 'Acme\Employee'); 221 | ``` 222 | 223 | ### Nullable Assertions 224 | 225 | All of the above assertions can be prefixed with `nullOr*()` to run the 226 | assertion only if the value is not `null`: 227 | 228 | ```php 229 | Assert::nullOrString($middleName, 'The middle name must be a string or null. Got: %s'); 230 | ``` 231 | 232 | ### Extending Assert 233 | 234 | The `Assert` class comes with a few methods, which can be overridden to change the class behaviour. You can also extend it to 235 | add your own assertions. 236 | 237 | #### Overriding methods 238 | 239 | Overriding the following methods in your assertion class allows you to change the behaviour of the assertions: 240 | 241 | * `public static function __callStatic($name, $arguments)` 242 | * This method is used to 'create' the `nullOr` and `all` versions of the assertions. 243 | * `protected static function valueToString($value)` 244 | * This method is used for error messages, to convert the value to a string value for displaying. You could use this for representing a value object with a `__toString` method for example. 245 | * `protected static function typeToString($value)` 246 | * This method is used for error messages, to convert a value to a string representing its type. 247 | * `protected static function strlen($value)` 248 | * This method is used to calculate string length for relevant methods, using the `mb_strlen` if available and useful. 249 | * `protected static function reportInvalidArgument($message)` 250 | * This method is called when an assertion fails, with the specified error message. Here you can throw your own exception, or log something. 251 | 252 | ## Static analysis support 253 | 254 | Where applicable, assertion functions are annotated to support Psalm's 255 | [Assertion syntax](https://psalm.dev/docs/annotating_code/assertion_syntax/). 256 | A dedicated [PHPStan Plugin](https://github.com/phpstan/phpstan-webmozart-assert) is 257 | required for proper type support. 258 | 259 | Authors 260 | ------- 261 | 262 | * [Bernhard Schussek] a.k.a. [@webmozart] 263 | * [The Community Contributors] 264 | 265 | Contribute 266 | ---------- 267 | 268 | Contributions to the package are always welcome! 269 | 270 | * Report any bugs or issues you find on the [issue tracker]. 271 | * You can grab the source code at the package's [Git repository]. 272 | 273 | License 274 | ------- 275 | 276 | All contents of this package are licensed under the [MIT license]. 277 | 278 | [beberlei/assert]: https://github.com/beberlei/assert 279 | [assert package]: https://github.com/beberlei/assert 280 | [Composer]: https://getcomposer.org 281 | [Bernhard Schussek]: https://webmozarts.com 282 | [The Community Contributors]: https://github.com/webmozart/assert/graphs/contributors 283 | [issue tracker]: https://github.com/webmozart/assert/issues 284 | [Git repository]: https://github.com/webmozart/assert 285 | [@webmozart]: https://twitter.com/webmozart 286 | [MIT license]: LICENSE 287 | [`Assert`]: src/Assert.php 288 | -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "webmozart/assert", 3 | "description": "Assertions to validate method input/output with nice error messages.", 4 | "license": "MIT", 5 | "keywords": [ 6 | "assert", 7 | "check", 8 | "validate" 9 | ], 10 | "authors": [ 11 | { 12 | "name": "Bernhard Schussek", 13 | "email": "bschussek@gmail.com" 14 | } 15 | ], 16 | "require": { 17 | "php": "^7.2 || ^8.0", 18 | "ext-ctype": "*" 19 | }, 20 | "suggest": { 21 | "ext-simplexml": "" 22 | }, 23 | "autoload": { 24 | "psr-4": { 25 | "Webmozart\\Assert\\": "src/" 26 | } 27 | }, 28 | "autoload-dev": { 29 | "psr-4": { 30 | "Webmozart\\Assert\\Bin\\": "bin/src", 31 | "Webmozart\\Assert\\Tests\\": "tests/" 32 | } 33 | }, 34 | "extra": { 35 | "branch-alias": { 36 | "dev-master": "1.10-dev" 37 | } 38 | }, 39 | "scripts": { 40 | "install-tools": [ 41 | "composer --working-dir=tools/php-cs-fixer install", 42 | "composer --working-dir=tools/phpunit install", 43 | "composer --working-dir=tools/psalm install", 44 | "composer --working-dir=tools/roave-bc-check install" 45 | ], 46 | "bc-check": "./tools/roave-bc-check/vendor/bin/roave-backward-compatibility-check", 47 | "cs-check" : "./tools/php-cs-fixer/vendor/bin/php-cs-fixer check", 48 | "cs-fix": "./tools/php-cs-fixer/vendor/bin/php-cs-fixer fix", 49 | "static-analysis": "./tools/psalm/vendor/bin/psalm --threads=4 --root=$(pwd)", 50 | "test": "./tools/phpunit/vendor/bin/phpunit" 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /src/Assert.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace Webmozart\Assert; 13 | 14 | use ArrayAccess; 15 | use BadMethodCallException; 16 | use Closure; 17 | use Countable; 18 | use DateTime; 19 | use DateTimeImmutable; 20 | use Exception; 21 | use ResourceBundle; 22 | use SimpleXMLElement; 23 | use Throwable; 24 | use Traversable; 25 | 26 | /** 27 | * Efficient assertions to validate the input/output of your methods. 28 | * 29 | * @since 1.0 30 | * 31 | * @author Bernhard Schussek 32 | */ 33 | class Assert 34 | { 35 | use Mixin; 36 | 37 | /** 38 | * @psalm-pure 39 | * 40 | * @psalm-assert string $value 41 | * 42 | * @param mixed $value 43 | * @param string $message 44 | * 45 | * @throws InvalidArgumentException 46 | */ 47 | public static function string($value, $message = '') 48 | { 49 | if (!\is_string($value)) { 50 | static::reportInvalidArgument(\sprintf( 51 | $message ?: 'Expected a string. Got: %s', 52 | static::typeToString($value) 53 | )); 54 | } 55 | } 56 | 57 | /** 58 | * @psalm-pure 59 | * 60 | * @psalm-assert non-empty-string $value 61 | * 62 | * @param mixed $value 63 | * @param string $message 64 | * 65 | * @throws InvalidArgumentException 66 | */ 67 | public static function stringNotEmpty($value, $message = '') 68 | { 69 | static::string($value, $message); 70 | static::notEq($value, '', $message); 71 | } 72 | 73 | /** 74 | * @psalm-pure 75 | * 76 | * @psalm-assert int $value 77 | * 78 | * @param mixed $value 79 | * @param string $message 80 | * 81 | * @throws InvalidArgumentException 82 | */ 83 | public static function integer($value, $message = '') 84 | { 85 | if (!\is_int($value)) { 86 | static::reportInvalidArgument(\sprintf( 87 | $message ?: 'Expected an integer. Got: %s', 88 | static::typeToString($value) 89 | )); 90 | } 91 | } 92 | 93 | /** 94 | * @psalm-pure 95 | * 96 | * @psalm-assert numeric $value 97 | * 98 | * @param mixed $value 99 | * @param string $message 100 | * 101 | * @throws InvalidArgumentException 102 | */ 103 | public static function integerish($value, $message = '') 104 | { 105 | if (!\is_numeric($value) || $value != (int) $value) { 106 | static::reportInvalidArgument(\sprintf( 107 | $message ?: 'Expected an integerish value. Got: %s', 108 | static::typeToString($value) 109 | )); 110 | } 111 | } 112 | 113 | /** 114 | * @psalm-pure 115 | * 116 | * @psalm-assert positive-int $value 117 | * 118 | * @param mixed $value 119 | * @param string $message 120 | * 121 | * @throws InvalidArgumentException 122 | */ 123 | public static function positiveInteger($value, $message = '') 124 | { 125 | if (!(\is_int($value) && $value > 0)) { 126 | static::reportInvalidArgument(\sprintf( 127 | $message ?: 'Expected a positive integer. Got: %s', 128 | static::valueToString($value) 129 | )); 130 | } 131 | } 132 | 133 | /** 134 | * @psalm-pure 135 | * 136 | * @psalm-assert float $value 137 | * 138 | * @param mixed $value 139 | * @param string $message 140 | * 141 | * @throws InvalidArgumentException 142 | */ 143 | public static function float($value, $message = '') 144 | { 145 | if (!\is_float($value)) { 146 | static::reportInvalidArgument(\sprintf( 147 | $message ?: 'Expected a float. Got: %s', 148 | static::typeToString($value) 149 | )); 150 | } 151 | } 152 | 153 | /** 154 | * @psalm-pure 155 | * 156 | * @psalm-assert numeric $value 157 | * 158 | * @param mixed $value 159 | * @param string $message 160 | * 161 | * @throws InvalidArgumentException 162 | */ 163 | public static function numeric($value, $message = '') 164 | { 165 | if (!\is_numeric($value)) { 166 | static::reportInvalidArgument(\sprintf( 167 | $message ?: 'Expected a numeric. Got: %s', 168 | static::typeToString($value) 169 | )); 170 | } 171 | } 172 | 173 | /** 174 | * @psalm-pure 175 | * 176 | * @psalm-assert positive-int|0 $value 177 | * 178 | * @param mixed $value 179 | * @param string $message 180 | * 181 | * @throws InvalidArgumentException 182 | */ 183 | public static function natural($value, $message = '') 184 | { 185 | if (!\is_int($value) || $value < 0) { 186 | static::reportInvalidArgument(\sprintf( 187 | $message ?: 'Expected a non-negative integer. Got: %s', 188 | static::valueToString($value) 189 | )); 190 | } 191 | } 192 | 193 | /** 194 | * @psalm-pure 195 | * 196 | * @psalm-assert bool $value 197 | * 198 | * @param mixed $value 199 | * @param string $message 200 | * 201 | * @throws InvalidArgumentException 202 | */ 203 | public static function boolean($value, $message = '') 204 | { 205 | if (!\is_bool($value)) { 206 | static::reportInvalidArgument(\sprintf( 207 | $message ?: 'Expected a boolean. Got: %s', 208 | static::typeToString($value) 209 | )); 210 | } 211 | } 212 | 213 | /** 214 | * @psalm-pure 215 | * 216 | * @psalm-assert scalar $value 217 | * 218 | * @param mixed $value 219 | * @param string $message 220 | * 221 | * @throws InvalidArgumentException 222 | */ 223 | public static function scalar($value, $message = '') 224 | { 225 | if (!\is_scalar($value)) { 226 | static::reportInvalidArgument(\sprintf( 227 | $message ?: 'Expected a scalar. Got: %s', 228 | static::typeToString($value) 229 | )); 230 | } 231 | } 232 | 233 | /** 234 | * @psalm-pure 235 | * 236 | * @psalm-assert object $value 237 | * 238 | * @param mixed $value 239 | * @param string $message 240 | * 241 | * @throws InvalidArgumentException 242 | */ 243 | public static function object($value, $message = '') 244 | { 245 | if (!\is_object($value)) { 246 | static::reportInvalidArgument(\sprintf( 247 | $message ?: 'Expected an object. Got: %s', 248 | static::typeToString($value) 249 | )); 250 | } 251 | } 252 | 253 | /** 254 | * @psalm-pure 255 | * 256 | * @psalm-assert resource $value 257 | * 258 | * @param mixed $value 259 | * @param string|null $type type of resource this should be. @see https://www.php.net/manual/en/function.get-resource-type.php 260 | * @param string $message 261 | * 262 | * @throws InvalidArgumentException 263 | */ 264 | public static function resource($value, $type = null, $message = '') 265 | { 266 | if (!\is_resource($value)) { 267 | static::reportInvalidArgument(\sprintf( 268 | $message ?: 'Expected a resource. Got: %s', 269 | static::typeToString($value), 270 | $type // User supplied message might include the second placeholder. 271 | )); 272 | } 273 | 274 | if ($type && $type !== \get_resource_type($value)) { 275 | static::reportInvalidArgument(\sprintf( 276 | $message ?: 'Expected a resource of type %2$s. Got: %s', 277 | static::typeToString($value), 278 | $type 279 | )); 280 | } 281 | } 282 | 283 | /** 284 | * @psalm-pure 285 | * 286 | * @psalm-assert callable $value 287 | * 288 | * @param mixed $value 289 | * @param string $message 290 | * 291 | * @throws InvalidArgumentException 292 | */ 293 | public static function isCallable($value, $message = '') 294 | { 295 | if (!\is_callable($value)) { 296 | static::reportInvalidArgument(\sprintf( 297 | $message ?: 'Expected a callable. Got: %s', 298 | static::typeToString($value) 299 | )); 300 | } 301 | } 302 | 303 | /** 304 | * @psalm-pure 305 | * 306 | * @psalm-assert array $value 307 | * 308 | * @param mixed $value 309 | * @param string $message 310 | * 311 | * @throws InvalidArgumentException 312 | */ 313 | public static function isArray($value, $message = '') 314 | { 315 | if (!\is_array($value)) { 316 | static::reportInvalidArgument(\sprintf( 317 | $message ?: 'Expected an array. Got: %s', 318 | static::typeToString($value) 319 | )); 320 | } 321 | } 322 | 323 | /** 324 | * @psalm-pure 325 | * 326 | * @psalm-assert iterable $value 327 | * 328 | * @deprecated use "isIterable" or "isInstanceOf" instead 329 | * 330 | * @param mixed $value 331 | * @param string $message 332 | * 333 | * @throws InvalidArgumentException 334 | */ 335 | public static function isTraversable($value, $message = '') 336 | { 337 | @\trigger_error( 338 | \sprintf( 339 | 'The "%s" assertion is deprecated. You should stop using it, as it will soon be removed in 2.0 version. Use "isIterable" or "isInstanceOf" instead.', 340 | __METHOD__ 341 | ), 342 | \E_USER_DEPRECATED 343 | ); 344 | 345 | if (!\is_array($value) && !($value instanceof Traversable)) { 346 | static::reportInvalidArgument(\sprintf( 347 | $message ?: 'Expected a traversable. Got: %s', 348 | static::typeToString($value) 349 | )); 350 | } 351 | } 352 | 353 | /** 354 | * @psalm-pure 355 | * 356 | * @psalm-assert array|ArrayAccess $value 357 | * 358 | * @param mixed $value 359 | * @param string $message 360 | * 361 | * @throws InvalidArgumentException 362 | */ 363 | public static function isArrayAccessible($value, $message = '') 364 | { 365 | if (!\is_array($value) && !($value instanceof ArrayAccess)) { 366 | static::reportInvalidArgument(\sprintf( 367 | $message ?: 'Expected an array accessible. Got: %s', 368 | static::typeToString($value) 369 | )); 370 | } 371 | } 372 | 373 | /** 374 | * @psalm-pure 375 | * 376 | * @psalm-assert countable $value 377 | * 378 | * @param mixed $value 379 | * @param string $message 380 | * 381 | * @throws InvalidArgumentException 382 | */ 383 | public static function isCountable($value, $message = '') 384 | { 385 | if ( 386 | !\is_array($value) 387 | && !($value instanceof Countable) 388 | && !($value instanceof ResourceBundle) 389 | && !($value instanceof SimpleXMLElement) 390 | ) { 391 | static::reportInvalidArgument(\sprintf( 392 | $message ?: 'Expected a countable. Got: %s', 393 | static::typeToString($value) 394 | )); 395 | } 396 | } 397 | 398 | /** 399 | * @psalm-pure 400 | * 401 | * @psalm-assert iterable $value 402 | * 403 | * @param mixed $value 404 | * @param string $message 405 | * 406 | * @throws InvalidArgumentException 407 | */ 408 | public static function isIterable($value, $message = '') 409 | { 410 | if (!\is_array($value) && !($value instanceof Traversable)) { 411 | static::reportInvalidArgument(\sprintf( 412 | $message ?: 'Expected an iterable. Got: %s', 413 | static::typeToString($value) 414 | )); 415 | } 416 | } 417 | 418 | /** 419 | * @psalm-pure 420 | * 421 | * @psalm-template ExpectedType of object 422 | * 423 | * @psalm-param class-string $class 424 | * 425 | * @psalm-assert ExpectedType $value 426 | * 427 | * @param mixed $value 428 | * @param string|object $class 429 | * @param string $message 430 | * 431 | * @throws InvalidArgumentException 432 | */ 433 | public static function isInstanceOf($value, $class, $message = '') 434 | { 435 | if (!($value instanceof $class)) { 436 | static::reportInvalidArgument(\sprintf( 437 | $message ?: 'Expected an instance of %2$s. Got: %s', 438 | static::typeToString($value), 439 | $class 440 | )); 441 | } 442 | } 443 | 444 | /** 445 | * @psalm-pure 446 | * 447 | * @psalm-template ExpectedType of object 448 | * 449 | * @psalm-param class-string $class 450 | * 451 | * @psalm-assert !ExpectedType $value 452 | * 453 | * @param mixed $value 454 | * @param string|object $class 455 | * @param string $message 456 | * 457 | * @throws InvalidArgumentException 458 | */ 459 | public static function notInstanceOf($value, $class, $message = '') 460 | { 461 | if ($value instanceof $class) { 462 | static::reportInvalidArgument(\sprintf( 463 | $message ?: 'Expected an instance other than %2$s. Got: %s', 464 | static::typeToString($value), 465 | $class 466 | )); 467 | } 468 | } 469 | 470 | /** 471 | * @psalm-pure 472 | * 473 | * @psalm-param array $classes 474 | * 475 | * @param mixed $value 476 | * @param array $classes 477 | * @param string $message 478 | * 479 | * @throws InvalidArgumentException 480 | */ 481 | public static function isInstanceOfAny($value, array $classes, $message = '') 482 | { 483 | foreach ($classes as $class) { 484 | if ($value instanceof $class) { 485 | return; 486 | } 487 | } 488 | 489 | static::reportInvalidArgument(\sprintf( 490 | $message ?: 'Expected an instance of any of %2$s. Got: %s', 491 | static::typeToString($value), 492 | \implode(', ', \array_map(array(static::class, 'valueToString'), $classes)) 493 | )); 494 | } 495 | 496 | /** 497 | * @psalm-pure 498 | * 499 | * @psalm-template ExpectedType of object 500 | * 501 | * @psalm-param class-string $class 502 | * 503 | * @psalm-assert ExpectedType|class-string $value 504 | * 505 | * @param object|string $value 506 | * @param string $class 507 | * @param string $message 508 | * 509 | * @throws InvalidArgumentException 510 | */ 511 | public static function isAOf($value, $class, $message = '') 512 | { 513 | static::string($class, 'Expected class as a string. Got: %s'); 514 | 515 | if (!\is_a($value, $class, \is_string($value))) { 516 | static::reportInvalidArgument(sprintf( 517 | $message ?: 'Expected an instance of this class or to this class among its parents "%2$s". Got: %s', 518 | static::valueToString($value), 519 | $class 520 | )); 521 | } 522 | } 523 | 524 | /** 525 | * @psalm-pure 526 | * 527 | * @psalm-template UnexpectedType of object 528 | * 529 | * @psalm-param class-string $class 530 | * 531 | * @psalm-assert !UnexpectedType $value 532 | * @psalm-assert !class-string $value 533 | * 534 | * @param object|string $value 535 | * @param string $class 536 | * @param string $message 537 | * 538 | * @throws InvalidArgumentException 539 | */ 540 | public static function isNotA($value, $class, $message = '') 541 | { 542 | static::string($class, 'Expected class as a string. Got: %s'); 543 | 544 | if (\is_a($value, $class, \is_string($value))) { 545 | static::reportInvalidArgument(sprintf( 546 | $message ?: 'Expected an instance of this class or to this class among its parents other than "%2$s". Got: %s', 547 | static::valueToString($value), 548 | $class 549 | )); 550 | } 551 | } 552 | 553 | /** 554 | * @psalm-pure 555 | * 556 | * @psalm-param array $classes 557 | * 558 | * @param object|string $value 559 | * @param string[] $classes 560 | * @param string $message 561 | * 562 | * @throws InvalidArgumentException 563 | */ 564 | public static function isAnyOf($value, array $classes, $message = '') 565 | { 566 | foreach ($classes as $class) { 567 | static::string($class, 'Expected class as a string. Got: %s'); 568 | 569 | if (\is_a($value, $class, \is_string($value))) { 570 | return; 571 | } 572 | } 573 | 574 | static::reportInvalidArgument(sprintf( 575 | $message ?: 'Expected an instance of any of this classes or any of those classes among their parents "%2$s". Got: %s', 576 | static::valueToString($value), 577 | \implode(', ', $classes) 578 | )); 579 | } 580 | 581 | /** 582 | * @psalm-pure 583 | * 584 | * @psalm-assert empty $value 585 | * 586 | * @param mixed $value 587 | * @param string $message 588 | * 589 | * @throws InvalidArgumentException 590 | */ 591 | public static function isEmpty($value, $message = '') 592 | { 593 | if (!empty($value)) { 594 | static::reportInvalidArgument(\sprintf( 595 | $message ?: 'Expected an empty value. Got: %s', 596 | static::valueToString($value) 597 | )); 598 | } 599 | } 600 | 601 | /** 602 | * @psalm-pure 603 | * 604 | * @psalm-assert !empty $value 605 | * 606 | * @param mixed $value 607 | * @param string $message 608 | * 609 | * @throws InvalidArgumentException 610 | */ 611 | public static function notEmpty($value, $message = '') 612 | { 613 | if (empty($value)) { 614 | static::reportInvalidArgument(\sprintf( 615 | $message ?: 'Expected a non-empty value. Got: %s', 616 | static::valueToString($value) 617 | )); 618 | } 619 | } 620 | 621 | /** 622 | * @psalm-pure 623 | * 624 | * @psalm-assert null $value 625 | * 626 | * @param mixed $value 627 | * @param string $message 628 | * 629 | * @throws InvalidArgumentException 630 | */ 631 | public static function null($value, $message = '') 632 | { 633 | if (null !== $value) { 634 | static::reportInvalidArgument(\sprintf( 635 | $message ?: 'Expected null. Got: %s', 636 | static::valueToString($value) 637 | )); 638 | } 639 | } 640 | 641 | /** 642 | * @psalm-pure 643 | * 644 | * @psalm-assert !null $value 645 | * 646 | * @param mixed $value 647 | * @param string $message 648 | * 649 | * @throws InvalidArgumentException 650 | */ 651 | public static function notNull($value, $message = '') 652 | { 653 | if (null === $value) { 654 | static::reportInvalidArgument( 655 | $message ?: 'Expected a value other than null.' 656 | ); 657 | } 658 | } 659 | 660 | /** 661 | * @psalm-pure 662 | * 663 | * @psalm-assert true $value 664 | * 665 | * @param mixed $value 666 | * @param string $message 667 | * 668 | * @throws InvalidArgumentException 669 | */ 670 | public static function true($value, $message = '') 671 | { 672 | if (true !== $value) { 673 | static::reportInvalidArgument(\sprintf( 674 | $message ?: 'Expected a value to be true. Got: %s', 675 | static::valueToString($value) 676 | )); 677 | } 678 | } 679 | 680 | /** 681 | * @psalm-pure 682 | * 683 | * @psalm-assert false $value 684 | * 685 | * @param mixed $value 686 | * @param string $message 687 | * 688 | * @throws InvalidArgumentException 689 | */ 690 | public static function false($value, $message = '') 691 | { 692 | if (false !== $value) { 693 | static::reportInvalidArgument(\sprintf( 694 | $message ?: 'Expected a value to be false. Got: %s', 695 | static::valueToString($value) 696 | )); 697 | } 698 | } 699 | 700 | /** 701 | * @psalm-pure 702 | * 703 | * @psalm-assert !false $value 704 | * 705 | * @param mixed $value 706 | * @param string $message 707 | * 708 | * @throws InvalidArgumentException 709 | */ 710 | public static function notFalse($value, $message = '') 711 | { 712 | if (false === $value) { 713 | static::reportInvalidArgument( 714 | $message ?: 'Expected a value other than false.' 715 | ); 716 | } 717 | } 718 | 719 | /** 720 | * @param mixed $value 721 | * @param string $message 722 | * 723 | * @throws InvalidArgumentException 724 | */ 725 | public static function ip($value, $message = '') 726 | { 727 | if (false === \filter_var($value, \FILTER_VALIDATE_IP)) { 728 | static::reportInvalidArgument(\sprintf( 729 | $message ?: 'Expected a value to be an IP. Got: %s', 730 | static::valueToString($value) 731 | )); 732 | } 733 | } 734 | 735 | /** 736 | * @param mixed $value 737 | * @param string $message 738 | * 739 | * @throws InvalidArgumentException 740 | */ 741 | public static function ipv4($value, $message = '') 742 | { 743 | if (false === \filter_var($value, \FILTER_VALIDATE_IP, \FILTER_FLAG_IPV4)) { 744 | static::reportInvalidArgument(\sprintf( 745 | $message ?: 'Expected a value to be an IPv4. Got: %s', 746 | static::valueToString($value) 747 | )); 748 | } 749 | } 750 | 751 | /** 752 | * @param mixed $value 753 | * @param string $message 754 | * 755 | * @throws InvalidArgumentException 756 | */ 757 | public static function ipv6($value, $message = '') 758 | { 759 | if (false === \filter_var($value, \FILTER_VALIDATE_IP, \FILTER_FLAG_IPV6)) { 760 | static::reportInvalidArgument(\sprintf( 761 | $message ?: 'Expected a value to be an IPv6. Got: %s', 762 | static::valueToString($value) 763 | )); 764 | } 765 | } 766 | 767 | /** 768 | * @param mixed $value 769 | * @param string $message 770 | * 771 | * @throws InvalidArgumentException 772 | */ 773 | public static function email($value, $message = '') 774 | { 775 | if (false === \filter_var($value, FILTER_VALIDATE_EMAIL)) { 776 | static::reportInvalidArgument(\sprintf( 777 | $message ?: 'Expected a value to be a valid e-mail address. Got: %s', 778 | static::valueToString($value) 779 | )); 780 | } 781 | } 782 | 783 | /** 784 | * Does non strict comparisons on the items, so ['3', 3] will not pass the assertion. 785 | * 786 | * @param array $values 787 | * @param string $message 788 | * 789 | * @throws InvalidArgumentException 790 | */ 791 | public static function uniqueValues(array $values, $message = '') 792 | { 793 | $allValues = \count($values); 794 | $uniqueValues = \count(\array_unique($values)); 795 | 796 | if ($allValues !== $uniqueValues) { 797 | $difference = $allValues - $uniqueValues; 798 | 799 | static::reportInvalidArgument(\sprintf( 800 | $message ?: 'Expected an array of unique values, but %s of them %s duplicated', 801 | $difference, 802 | 1 === $difference ? 'is' : 'are' 803 | )); 804 | } 805 | } 806 | 807 | /** 808 | * @param mixed $value 809 | * @param mixed $expect 810 | * @param string $message 811 | * 812 | * @throws InvalidArgumentException 813 | */ 814 | public static function eq($value, $expect, $message = '') 815 | { 816 | if ($expect != $value) { 817 | static::reportInvalidArgument(\sprintf( 818 | $message ?: 'Expected a value equal to %2$s. Got: %s', 819 | static::valueToString($value), 820 | static::valueToString($expect) 821 | )); 822 | } 823 | } 824 | 825 | /** 826 | * @param mixed $value 827 | * @param mixed $expect 828 | * @param string $message 829 | * 830 | * @throws InvalidArgumentException 831 | */ 832 | public static function notEq($value, $expect, $message = '') 833 | { 834 | if ($expect == $value) { 835 | static::reportInvalidArgument(\sprintf( 836 | $message ?: 'Expected a different value than %s.', 837 | static::valueToString($expect) 838 | )); 839 | } 840 | } 841 | 842 | /** 843 | * @psalm-pure 844 | * 845 | * @param mixed $value 846 | * @param mixed $expect 847 | * @param string $message 848 | * 849 | * @throws InvalidArgumentException 850 | */ 851 | public static function same($value, $expect, $message = '') 852 | { 853 | if ($expect !== $value) { 854 | static::reportInvalidArgument(\sprintf( 855 | $message ?: 'Expected a value identical to %2$s. Got: %s', 856 | static::valueToString($value), 857 | static::valueToString($expect) 858 | )); 859 | } 860 | } 861 | 862 | /** 863 | * @psalm-pure 864 | * 865 | * @param mixed $value 866 | * @param mixed $expect 867 | * @param string $message 868 | * 869 | * @throws InvalidArgumentException 870 | */ 871 | public static function notSame($value, $expect, $message = '') 872 | { 873 | if ($expect === $value) { 874 | static::reportInvalidArgument(\sprintf( 875 | $message ?: 'Expected a value not identical to %s.', 876 | static::valueToString($expect) 877 | )); 878 | } 879 | } 880 | 881 | /** 882 | * @psalm-pure 883 | * 884 | * @param mixed $value 885 | * @param mixed $limit 886 | * @param string $message 887 | * 888 | * @throws InvalidArgumentException 889 | */ 890 | public static function greaterThan($value, $limit, $message = '') 891 | { 892 | if ($value <= $limit) { 893 | static::reportInvalidArgument(\sprintf( 894 | $message ?: 'Expected a value greater than %2$s. Got: %s', 895 | static::valueToString($value), 896 | static::valueToString($limit) 897 | )); 898 | } 899 | } 900 | 901 | /** 902 | * @psalm-pure 903 | * 904 | * @param mixed $value 905 | * @param mixed $limit 906 | * @param string $message 907 | * 908 | * @throws InvalidArgumentException 909 | */ 910 | public static function greaterThanEq($value, $limit, $message = '') 911 | { 912 | if ($value < $limit) { 913 | static::reportInvalidArgument(\sprintf( 914 | $message ?: 'Expected a value greater than or equal to %2$s. Got: %s', 915 | static::valueToString($value), 916 | static::valueToString($limit) 917 | )); 918 | } 919 | } 920 | 921 | /** 922 | * @psalm-pure 923 | * 924 | * @param mixed $value 925 | * @param mixed $limit 926 | * @param string $message 927 | * 928 | * @throws InvalidArgumentException 929 | */ 930 | public static function lessThan($value, $limit, $message = '') 931 | { 932 | if ($value >= $limit) { 933 | static::reportInvalidArgument(\sprintf( 934 | $message ?: 'Expected a value less than %2$s. Got: %s', 935 | static::valueToString($value), 936 | static::valueToString($limit) 937 | )); 938 | } 939 | } 940 | 941 | /** 942 | * @psalm-pure 943 | * 944 | * @param mixed $value 945 | * @param mixed $limit 946 | * @param string $message 947 | * 948 | * @throws InvalidArgumentException 949 | */ 950 | public static function lessThanEq($value, $limit, $message = '') 951 | { 952 | if ($value > $limit) { 953 | static::reportInvalidArgument(\sprintf( 954 | $message ?: 'Expected a value less than or equal to %2$s. Got: %s', 955 | static::valueToString($value), 956 | static::valueToString($limit) 957 | )); 958 | } 959 | } 960 | 961 | /** 962 | * Inclusive range, so Assert::(3, 3, 5) passes. 963 | * 964 | * @psalm-pure 965 | * 966 | * @param mixed $value 967 | * @param mixed $min 968 | * @param mixed $max 969 | * @param string $message 970 | * 971 | * @throws InvalidArgumentException 972 | */ 973 | public static function range($value, $min, $max, $message = '') 974 | { 975 | if ($value < $min || $value > $max) { 976 | static::reportInvalidArgument(\sprintf( 977 | $message ?: 'Expected a value between %2$s and %3$s. Got: %s', 978 | static::valueToString($value), 979 | static::valueToString($min), 980 | static::valueToString($max) 981 | )); 982 | } 983 | } 984 | 985 | /** 986 | * A more human-readable alias of Assert::inArray(). 987 | * 988 | * @psalm-pure 989 | * 990 | * @param mixed $value 991 | * @param array $values 992 | * @param string $message 993 | * 994 | * @throws InvalidArgumentException 995 | */ 996 | public static function oneOf($value, array $values, $message = '') 997 | { 998 | static::inArray($value, $values, $message); 999 | } 1000 | 1001 | /** 1002 | * Does strict comparison, so Assert::inArray(3, ['3']) does not pass the assertion. 1003 | * 1004 | * @psalm-pure 1005 | * 1006 | * @param mixed $value 1007 | * @param array $values 1008 | * @param string $message 1009 | * 1010 | * @throws InvalidArgumentException 1011 | */ 1012 | public static function inArray($value, array $values, $message = '') 1013 | { 1014 | if (!\in_array($value, $values, true)) { 1015 | static::reportInvalidArgument(\sprintf( 1016 | $message ?: 'Expected one of: %2$s. Got: %s', 1017 | static::valueToString($value), 1018 | \implode(', ', \array_map(array(static::class, 'valueToString'), $values)) 1019 | )); 1020 | } 1021 | } 1022 | 1023 | /** 1024 | * @psalm-pure 1025 | * 1026 | * @param string $value 1027 | * @param string $subString 1028 | * @param string $message 1029 | * 1030 | * @throws InvalidArgumentException 1031 | */ 1032 | public static function contains($value, $subString, $message = '') 1033 | { 1034 | if (false === \strpos($value, $subString)) { 1035 | static::reportInvalidArgument(\sprintf( 1036 | $message ?: 'Expected a value to contain %2$s. Got: %s', 1037 | static::valueToString($value), 1038 | static::valueToString($subString) 1039 | )); 1040 | } 1041 | } 1042 | 1043 | /** 1044 | * @psalm-pure 1045 | * 1046 | * @param string $value 1047 | * @param string $subString 1048 | * @param string $message 1049 | * 1050 | * @throws InvalidArgumentException 1051 | */ 1052 | public static function notContains($value, $subString, $message = '') 1053 | { 1054 | if (false !== \strpos($value, $subString)) { 1055 | static::reportInvalidArgument(\sprintf( 1056 | $message ?: '%2$s was not expected to be contained in a value. Got: %s', 1057 | static::valueToString($value), 1058 | static::valueToString($subString) 1059 | )); 1060 | } 1061 | } 1062 | 1063 | /** 1064 | * @psalm-pure 1065 | * 1066 | * @param string $value 1067 | * @param string $message 1068 | * 1069 | * @throws InvalidArgumentException 1070 | */ 1071 | public static function notWhitespaceOnly($value, $message = '') 1072 | { 1073 | if (\preg_match('/^\s*$/', $value)) { 1074 | static::reportInvalidArgument(\sprintf( 1075 | $message ?: 'Expected a non-whitespace string. Got: %s', 1076 | static::valueToString($value) 1077 | )); 1078 | } 1079 | } 1080 | 1081 | /** 1082 | * @psalm-pure 1083 | * 1084 | * @param string $value 1085 | * @param string $prefix 1086 | * @param string $message 1087 | * 1088 | * @throws InvalidArgumentException 1089 | */ 1090 | public static function startsWith($value, $prefix, $message = '') 1091 | { 1092 | if (0 !== \strpos($value, $prefix)) { 1093 | static::reportInvalidArgument(\sprintf( 1094 | $message ?: 'Expected a value to start with %2$s. Got: %s', 1095 | static::valueToString($value), 1096 | static::valueToString($prefix) 1097 | )); 1098 | } 1099 | } 1100 | 1101 | /** 1102 | * @psalm-pure 1103 | * 1104 | * @param string $value 1105 | * @param string $prefix 1106 | * @param string $message 1107 | * 1108 | * @throws InvalidArgumentException 1109 | */ 1110 | public static function notStartsWith($value, $prefix, $message = '') 1111 | { 1112 | if (0 === \strpos($value, $prefix)) { 1113 | static::reportInvalidArgument(\sprintf( 1114 | $message ?: 'Expected a value not to start with %2$s. Got: %s', 1115 | static::valueToString($value), 1116 | static::valueToString($prefix) 1117 | )); 1118 | } 1119 | } 1120 | 1121 | /** 1122 | * @psalm-pure 1123 | * 1124 | * @param mixed $value 1125 | * @param string $message 1126 | * 1127 | * @throws InvalidArgumentException 1128 | */ 1129 | public static function startsWithLetter($value, $message = '') 1130 | { 1131 | static::string($value); 1132 | 1133 | $valid = isset($value[0]); 1134 | 1135 | if ($valid) { 1136 | $locale = \setlocale(LC_CTYPE, 0); 1137 | \setlocale(LC_CTYPE, 'C'); 1138 | $valid = \ctype_alpha($value[0]); 1139 | \setlocale(LC_CTYPE, $locale); 1140 | } 1141 | 1142 | if (!$valid) { 1143 | static::reportInvalidArgument(\sprintf( 1144 | $message ?: 'Expected a value to start with a letter. Got: %s', 1145 | static::valueToString($value) 1146 | )); 1147 | } 1148 | } 1149 | 1150 | /** 1151 | * @psalm-pure 1152 | * 1153 | * @param string $value 1154 | * @param string $suffix 1155 | * @param string $message 1156 | * 1157 | * @throws InvalidArgumentException 1158 | */ 1159 | public static function endsWith($value, $suffix, $message = '') 1160 | { 1161 | if ($suffix !== \substr($value, -\strlen($suffix))) { 1162 | static::reportInvalidArgument(\sprintf( 1163 | $message ?: 'Expected a value to end with %2$s. Got: %s', 1164 | static::valueToString($value), 1165 | static::valueToString($suffix) 1166 | )); 1167 | } 1168 | } 1169 | 1170 | /** 1171 | * @psalm-pure 1172 | * 1173 | * @param string $value 1174 | * @param string $suffix 1175 | * @param string $message 1176 | * 1177 | * @throws InvalidArgumentException 1178 | */ 1179 | public static function notEndsWith($value, $suffix, $message = '') 1180 | { 1181 | if ($suffix === \substr($value, -\strlen($suffix))) { 1182 | static::reportInvalidArgument(\sprintf( 1183 | $message ?: 'Expected a value not to end with %2$s. Got: %s', 1184 | static::valueToString($value), 1185 | static::valueToString($suffix) 1186 | )); 1187 | } 1188 | } 1189 | 1190 | /** 1191 | * @psalm-pure 1192 | * 1193 | * @param string $value 1194 | * @param string $pattern 1195 | * @param string $message 1196 | * 1197 | * @throws InvalidArgumentException 1198 | */ 1199 | public static function regex($value, $pattern, $message = '') 1200 | { 1201 | if (!\preg_match($pattern, $value)) { 1202 | static::reportInvalidArgument(\sprintf( 1203 | $message ?: 'The value %s does not match the expected pattern.', 1204 | static::valueToString($value) 1205 | )); 1206 | } 1207 | } 1208 | 1209 | /** 1210 | * @psalm-pure 1211 | * 1212 | * @param string $value 1213 | * @param string $pattern 1214 | * @param string $message 1215 | * 1216 | * @throws InvalidArgumentException 1217 | */ 1218 | public static function notRegex($value, $pattern, $message = '') 1219 | { 1220 | if (\preg_match($pattern, $value, $matches, PREG_OFFSET_CAPTURE)) { 1221 | static::reportInvalidArgument(\sprintf( 1222 | $message ?: 'The value %s matches the pattern %s (at offset %d).', 1223 | static::valueToString($value), 1224 | static::valueToString($pattern), 1225 | $matches[0][1] 1226 | )); 1227 | } 1228 | } 1229 | 1230 | /** 1231 | * @psalm-pure 1232 | * 1233 | * @param mixed $value 1234 | * @param string $message 1235 | * 1236 | * @throws InvalidArgumentException 1237 | */ 1238 | public static function unicodeLetters($value, $message = '') 1239 | { 1240 | static::string($value); 1241 | 1242 | if (!\preg_match('/^\p{L}+$/u', $value)) { 1243 | static::reportInvalidArgument(\sprintf( 1244 | $message ?: 'Expected a value to contain only Unicode letters. Got: %s', 1245 | static::valueToString($value) 1246 | )); 1247 | } 1248 | } 1249 | 1250 | /** 1251 | * @psalm-pure 1252 | * 1253 | * @param mixed $value 1254 | * @param string $message 1255 | * 1256 | * @throws InvalidArgumentException 1257 | */ 1258 | public static function alpha($value, $message = '') 1259 | { 1260 | static::string($value); 1261 | 1262 | $locale = \setlocale(LC_CTYPE, 0); 1263 | \setlocale(LC_CTYPE, 'C'); 1264 | $valid = !\ctype_alpha($value); 1265 | \setlocale(LC_CTYPE, $locale); 1266 | 1267 | if ($valid) { 1268 | static::reportInvalidArgument(\sprintf( 1269 | $message ?: 'Expected a value to contain only letters. Got: %s', 1270 | static::valueToString($value) 1271 | )); 1272 | } 1273 | } 1274 | 1275 | /** 1276 | * @psalm-pure 1277 | * 1278 | * @param string $value 1279 | * @param string $message 1280 | * 1281 | * @throws InvalidArgumentException 1282 | */ 1283 | public static function digits($value, $message = '') 1284 | { 1285 | $locale = \setlocale(LC_CTYPE, 0); 1286 | \setlocale(LC_CTYPE, 'C'); 1287 | $valid = !\ctype_digit($value); 1288 | \setlocale(LC_CTYPE, $locale); 1289 | 1290 | if ($valid) { 1291 | static::reportInvalidArgument(\sprintf( 1292 | $message ?: 'Expected a value to contain digits only. Got: %s', 1293 | static::valueToString($value) 1294 | )); 1295 | } 1296 | } 1297 | 1298 | /** 1299 | * @psalm-pure 1300 | * 1301 | * @param string $value 1302 | * @param string $message 1303 | * 1304 | * @throws InvalidArgumentException 1305 | */ 1306 | public static function alnum($value, $message = '') 1307 | { 1308 | $locale = \setlocale(LC_CTYPE, 0); 1309 | \setlocale(LC_CTYPE, 'C'); 1310 | $valid = !\ctype_alnum($value); 1311 | \setlocale(LC_CTYPE, $locale); 1312 | 1313 | if ($valid) { 1314 | static::reportInvalidArgument(\sprintf( 1315 | $message ?: 'Expected a value to contain letters and digits only. Got: %s', 1316 | static::valueToString($value) 1317 | )); 1318 | } 1319 | } 1320 | 1321 | /** 1322 | * @psalm-pure 1323 | * 1324 | * @psalm-assert lowercase-string $value 1325 | * 1326 | * @param string $value 1327 | * @param string $message 1328 | * 1329 | * @throws InvalidArgumentException 1330 | */ 1331 | public static function lower($value, $message = '') 1332 | { 1333 | $locale = \setlocale(LC_CTYPE, 0); 1334 | \setlocale(LC_CTYPE, 'C'); 1335 | $valid = !\ctype_lower($value); 1336 | \setlocale(LC_CTYPE, $locale); 1337 | 1338 | if ($valid) { 1339 | static::reportInvalidArgument(\sprintf( 1340 | $message ?: 'Expected a value to contain lowercase characters only. Got: %s', 1341 | static::valueToString($value) 1342 | )); 1343 | } 1344 | } 1345 | 1346 | /** 1347 | * @psalm-pure 1348 | * 1349 | * @psalm-assert !lowercase-string $value 1350 | * 1351 | * @param string $value 1352 | * @param string $message 1353 | * 1354 | * @throws InvalidArgumentException 1355 | */ 1356 | public static function upper($value, $message = '') 1357 | { 1358 | $locale = \setlocale(LC_CTYPE, 0); 1359 | \setlocale(LC_CTYPE, 'C'); 1360 | $valid = !\ctype_upper($value); 1361 | \setlocale(LC_CTYPE, $locale); 1362 | 1363 | if ($valid) { 1364 | static::reportInvalidArgument(\sprintf( 1365 | $message ?: 'Expected a value to contain uppercase characters only. Got: %s', 1366 | static::valueToString($value) 1367 | )); 1368 | } 1369 | } 1370 | 1371 | /** 1372 | * @psalm-pure 1373 | * 1374 | * @param string $value 1375 | * @param int $length 1376 | * @param string $message 1377 | * 1378 | * @throws InvalidArgumentException 1379 | */ 1380 | public static function length($value, $length, $message = '') 1381 | { 1382 | if ($length !== static::strlen($value)) { 1383 | static::reportInvalidArgument(\sprintf( 1384 | $message ?: 'Expected a value to contain %2$s characters. Got: %s', 1385 | static::valueToString($value), 1386 | $length 1387 | )); 1388 | } 1389 | } 1390 | 1391 | /** 1392 | * Inclusive min. 1393 | * 1394 | * @psalm-pure 1395 | * 1396 | * @param string $value 1397 | * @param int|float $min 1398 | * @param string $message 1399 | * 1400 | * @throws InvalidArgumentException 1401 | */ 1402 | public static function minLength($value, $min, $message = '') 1403 | { 1404 | if (static::strlen($value) < $min) { 1405 | static::reportInvalidArgument(\sprintf( 1406 | $message ?: 'Expected a value to contain at least %2$s characters. Got: %s', 1407 | static::valueToString($value), 1408 | $min 1409 | )); 1410 | } 1411 | } 1412 | 1413 | /** 1414 | * Inclusive max. 1415 | * 1416 | * @psalm-pure 1417 | * 1418 | * @param string $value 1419 | * @param int|float $max 1420 | * @param string $message 1421 | * 1422 | * @throws InvalidArgumentException 1423 | */ 1424 | public static function maxLength($value, $max, $message = '') 1425 | { 1426 | if (static::strlen($value) > $max) { 1427 | static::reportInvalidArgument(\sprintf( 1428 | $message ?: 'Expected a value to contain at most %2$s characters. Got: %s', 1429 | static::valueToString($value), 1430 | $max 1431 | )); 1432 | } 1433 | } 1434 | 1435 | /** 1436 | * Inclusive , so Assert::lengthBetween('asd', 3, 5); passes the assertion. 1437 | * 1438 | * @psalm-pure 1439 | * 1440 | * @param string $value 1441 | * @param int|float $min 1442 | * @param int|float $max 1443 | * @param string $message 1444 | * 1445 | * @throws InvalidArgumentException 1446 | */ 1447 | public static function lengthBetween($value, $min, $max, $message = '') 1448 | { 1449 | $length = static::strlen($value); 1450 | 1451 | if ($length < $min || $length > $max) { 1452 | static::reportInvalidArgument(\sprintf( 1453 | $message ?: 'Expected a value to contain between %2$s and %3$s characters. Got: %s', 1454 | static::valueToString($value), 1455 | $min, 1456 | $max 1457 | )); 1458 | } 1459 | } 1460 | 1461 | /** 1462 | * Will also pass if $value is a directory, use Assert::file() instead if you need to be sure it is a file. 1463 | * 1464 | * @param mixed $value 1465 | * @param string $message 1466 | * 1467 | * @throws InvalidArgumentException 1468 | */ 1469 | public static function fileExists($value, $message = '') 1470 | { 1471 | if (!\file_exists($value)) { 1472 | static::reportInvalidArgument(\sprintf( 1473 | $message ?: 'The path %s does not exist.', 1474 | static::valueToString($value) 1475 | )); 1476 | } 1477 | } 1478 | 1479 | /** 1480 | * @param mixed $value 1481 | * @param string $message 1482 | * 1483 | * @throws InvalidArgumentException 1484 | */ 1485 | public static function file($value, $message = '') 1486 | { 1487 | if (!\is_file($value)) { 1488 | static::reportInvalidArgument(\sprintf( 1489 | $message ?: 'The path %s is not a file.', 1490 | static::valueToString($value) 1491 | )); 1492 | } 1493 | } 1494 | 1495 | /** 1496 | * @param mixed $value 1497 | * @param string $message 1498 | * 1499 | * @throws InvalidArgumentException 1500 | */ 1501 | public static function directory($value, $message = '') 1502 | { 1503 | if (!\is_dir($value)) { 1504 | static::reportInvalidArgument(\sprintf( 1505 | $message ?: 'The path %s is not a directory.', 1506 | static::valueToString($value) 1507 | )); 1508 | } 1509 | } 1510 | 1511 | /** 1512 | * @param string $value 1513 | * @param string $message 1514 | * 1515 | * @throws InvalidArgumentException 1516 | */ 1517 | public static function readable($value, $message = '') 1518 | { 1519 | if (!\is_readable($value)) { 1520 | static::reportInvalidArgument(\sprintf( 1521 | $message ?: 'The path %s is not readable.', 1522 | static::valueToString($value) 1523 | )); 1524 | } 1525 | } 1526 | 1527 | /** 1528 | * @param string $value 1529 | * @param string $message 1530 | * 1531 | * @throws InvalidArgumentException 1532 | */ 1533 | public static function writable($value, $message = '') 1534 | { 1535 | if (!\is_writable($value)) { 1536 | static::reportInvalidArgument(\sprintf( 1537 | $message ?: 'The path %s is not writable.', 1538 | static::valueToString($value) 1539 | )); 1540 | } 1541 | } 1542 | 1543 | /** 1544 | * @psalm-assert class-string $value 1545 | * 1546 | * @param mixed $value 1547 | * @param string $message 1548 | * 1549 | * @throws InvalidArgumentException 1550 | */ 1551 | public static function classExists($value, $message = '') 1552 | { 1553 | if (!\class_exists($value)) { 1554 | static::reportInvalidArgument(\sprintf( 1555 | $message ?: 'Expected an existing class name. Got: %s', 1556 | static::valueToString($value) 1557 | )); 1558 | } 1559 | } 1560 | 1561 | /** 1562 | * @psalm-pure 1563 | * 1564 | * @psalm-template ExpectedType of object 1565 | * 1566 | * @psalm-param class-string $class 1567 | * 1568 | * @psalm-assert class-string|ExpectedType $value 1569 | * 1570 | * @param mixed $value 1571 | * @param string|object $class 1572 | * @param string $message 1573 | * 1574 | * @throws InvalidArgumentException 1575 | */ 1576 | public static function subclassOf($value, $class, $message = '') 1577 | { 1578 | if (!\is_subclass_of($value, $class)) { 1579 | static::reportInvalidArgument(\sprintf( 1580 | $message ?: 'Expected a sub-class of %2$s. Got: %s', 1581 | static::valueToString($value), 1582 | static::valueToString($class) 1583 | )); 1584 | } 1585 | } 1586 | 1587 | /** 1588 | * @psalm-assert class-string $value 1589 | * 1590 | * @param mixed $value 1591 | * @param string $message 1592 | * 1593 | * @throws InvalidArgumentException 1594 | */ 1595 | public static function interfaceExists($value, $message = '') 1596 | { 1597 | if (!\interface_exists($value)) { 1598 | static::reportInvalidArgument(\sprintf( 1599 | $message ?: 'Expected an existing interface name. got %s', 1600 | static::valueToString($value) 1601 | )); 1602 | } 1603 | } 1604 | 1605 | /** 1606 | * @psalm-pure 1607 | * 1608 | * @psalm-template ExpectedType of object 1609 | * 1610 | * @psalm-param class-string $interface 1611 | * 1612 | * @psalm-assert class-string|ExpectedType $value 1613 | * 1614 | * @param mixed $value 1615 | * @param mixed $interface 1616 | * @param string $message 1617 | * 1618 | * @throws InvalidArgumentException 1619 | */ 1620 | public static function implementsInterface($value, $interface, $message = '') 1621 | { 1622 | if (!\in_array($interface, \class_implements($value))) { 1623 | static::reportInvalidArgument(\sprintf( 1624 | $message ?: 'Expected an implementation of %2$s. Got: %s', 1625 | static::valueToString($value), 1626 | static::valueToString($interface) 1627 | )); 1628 | } 1629 | } 1630 | 1631 | /** 1632 | * @psalm-pure 1633 | * 1634 | * @psalm-param class-string|object $classOrObject 1635 | * 1636 | * @param string|object $classOrObject 1637 | * @param mixed $property 1638 | * @param string $message 1639 | * 1640 | * @throws InvalidArgumentException 1641 | */ 1642 | public static function propertyExists($classOrObject, $property, $message = '') 1643 | { 1644 | if (!\property_exists($classOrObject, $property)) { 1645 | static::reportInvalidArgument(\sprintf( 1646 | $message ?: 'Expected the property %s to exist.', 1647 | static::valueToString($property) 1648 | )); 1649 | } 1650 | } 1651 | 1652 | /** 1653 | * @psalm-pure 1654 | * 1655 | * @psalm-param class-string|object $classOrObject 1656 | * 1657 | * @param string|object $classOrObject 1658 | * @param mixed $property 1659 | * @param string $message 1660 | * 1661 | * @throws InvalidArgumentException 1662 | */ 1663 | public static function propertyNotExists($classOrObject, $property, $message = '') 1664 | { 1665 | if (\property_exists($classOrObject, $property)) { 1666 | static::reportInvalidArgument(\sprintf( 1667 | $message ?: 'Expected the property %s to not exist.', 1668 | static::valueToString($property) 1669 | )); 1670 | } 1671 | } 1672 | 1673 | /** 1674 | * @psalm-pure 1675 | * 1676 | * @psalm-param class-string|object $classOrObject 1677 | * 1678 | * @param string|object $classOrObject 1679 | * @param mixed $method 1680 | * @param string $message 1681 | * 1682 | * @throws InvalidArgumentException 1683 | */ 1684 | public static function methodExists($classOrObject, $method, $message = '') 1685 | { 1686 | if (!(\is_string($classOrObject) || \is_object($classOrObject)) || !\method_exists($classOrObject, $method)) { 1687 | static::reportInvalidArgument(\sprintf( 1688 | $message ?: 'Expected the method %s to exist.', 1689 | static::valueToString($method) 1690 | )); 1691 | } 1692 | } 1693 | 1694 | /** 1695 | * @psalm-pure 1696 | * 1697 | * @psalm-param class-string|object $classOrObject 1698 | * 1699 | * @param string|object $classOrObject 1700 | * @param mixed $method 1701 | * @param string $message 1702 | * 1703 | * @throws InvalidArgumentException 1704 | */ 1705 | public static function methodNotExists($classOrObject, $method, $message = '') 1706 | { 1707 | if ((\is_string($classOrObject) || \is_object($classOrObject)) && \method_exists($classOrObject, $method)) { 1708 | static::reportInvalidArgument(\sprintf( 1709 | $message ?: 'Expected the method %s to not exist.', 1710 | static::valueToString($method) 1711 | )); 1712 | } 1713 | } 1714 | 1715 | /** 1716 | * @psalm-pure 1717 | * 1718 | * @param array $array 1719 | * @param string|int $key 1720 | * @param string $message 1721 | * 1722 | * @throws InvalidArgumentException 1723 | */ 1724 | public static function keyExists($array, $key, $message = '') 1725 | { 1726 | if (!(isset($array[$key]) || \array_key_exists($key, $array))) { 1727 | static::reportInvalidArgument(\sprintf( 1728 | $message ?: 'Expected the key %s to exist.', 1729 | static::valueToString($key) 1730 | )); 1731 | } 1732 | } 1733 | 1734 | /** 1735 | * @psalm-pure 1736 | * 1737 | * @param array $array 1738 | * @param string|int $key 1739 | * @param string $message 1740 | * 1741 | * @throws InvalidArgumentException 1742 | */ 1743 | public static function keyNotExists($array, $key, $message = '') 1744 | { 1745 | if (isset($array[$key]) || \array_key_exists($key, $array)) { 1746 | static::reportInvalidArgument(\sprintf( 1747 | $message ?: 'Expected the key %s to not exist.', 1748 | static::valueToString($key) 1749 | )); 1750 | } 1751 | } 1752 | 1753 | /** 1754 | * Checks if a value is a valid array key (int or string). 1755 | * 1756 | * @psalm-pure 1757 | * 1758 | * @psalm-assert array-key $value 1759 | * 1760 | * @param mixed $value 1761 | * @param string $message 1762 | * 1763 | * @throws InvalidArgumentException 1764 | */ 1765 | public static function validArrayKey($value, $message = '') 1766 | { 1767 | if (!(\is_int($value) || \is_string($value))) { 1768 | static::reportInvalidArgument(\sprintf( 1769 | $message ?: 'Expected string or integer. Got: %s', 1770 | static::typeToString($value) 1771 | )); 1772 | } 1773 | } 1774 | 1775 | /** 1776 | * Does not check if $array is countable, this can generate a warning on php versions after 7.2. 1777 | * 1778 | * @param Countable|array $array 1779 | * @param int $number 1780 | * @param string $message 1781 | * 1782 | * @throws InvalidArgumentException 1783 | */ 1784 | public static function count($array, $number, $message = '') 1785 | { 1786 | static::eq( 1787 | \count($array), 1788 | $number, 1789 | \sprintf( 1790 | $message ?: 'Expected an array to contain %d elements. Got: %d.', 1791 | $number, 1792 | \count($array) 1793 | ) 1794 | ); 1795 | } 1796 | 1797 | /** 1798 | * Does not check if $array is countable, this can generate a warning on php versions after 7.2. 1799 | * 1800 | * @param Countable|array $array 1801 | * @param int|float $min 1802 | * @param string $message 1803 | * 1804 | * @throws InvalidArgumentException 1805 | */ 1806 | public static function minCount($array, $min, $message = '') 1807 | { 1808 | if (\count($array) < $min) { 1809 | static::reportInvalidArgument(\sprintf( 1810 | $message ?: 'Expected an array to contain at least %2$d elements. Got: %d', 1811 | \count($array), 1812 | $min 1813 | )); 1814 | } 1815 | } 1816 | 1817 | /** 1818 | * Does not check if $array is countable, this can generate a warning on php versions after 7.2. 1819 | * 1820 | * @param Countable|array $array 1821 | * @param int|float $max 1822 | * @param string $message 1823 | * 1824 | * @throws InvalidArgumentException 1825 | */ 1826 | public static function maxCount($array, $max, $message = '') 1827 | { 1828 | if (\count($array) > $max) { 1829 | static::reportInvalidArgument(\sprintf( 1830 | $message ?: 'Expected an array to contain at most %2$d elements. Got: %d', 1831 | \count($array), 1832 | $max 1833 | )); 1834 | } 1835 | } 1836 | 1837 | /** 1838 | * Does not check if $array is countable, this can generate a warning on php versions after 7.2. 1839 | * 1840 | * @param Countable|array $array 1841 | * @param int|float $min 1842 | * @param int|float $max 1843 | * @param string $message 1844 | * 1845 | * @throws InvalidArgumentException 1846 | */ 1847 | public static function countBetween($array, $min, $max, $message = '') 1848 | { 1849 | $count = \count($array); 1850 | 1851 | if ($count < $min || $count > $max) { 1852 | static::reportInvalidArgument(\sprintf( 1853 | $message ?: 'Expected an array to contain between %2$d and %3$d elements. Got: %d', 1854 | $count, 1855 | $min, 1856 | $max 1857 | )); 1858 | } 1859 | } 1860 | 1861 | /** 1862 | * @psalm-pure 1863 | * 1864 | * @psalm-assert list $array 1865 | * 1866 | * @param mixed $array 1867 | * @param string $message 1868 | * 1869 | * @throws InvalidArgumentException 1870 | */ 1871 | public static function isList($array, $message = '') 1872 | { 1873 | if (!\is_array($array)) { 1874 | static::reportInvalidArgument( 1875 | $message ?: 'Expected list - non-associative array.' 1876 | ); 1877 | } 1878 | 1879 | if (\function_exists('array_is_list')) { 1880 | if (!\array_is_list($array)) { 1881 | static::reportInvalidArgument( 1882 | $message ?: 'Expected list - non-associative array.' 1883 | ); 1884 | } 1885 | 1886 | return; 1887 | } 1888 | 1889 | if (array() === $array) { 1890 | return; 1891 | } 1892 | 1893 | $keys = array_keys($array); 1894 | if (array_keys($keys) !== $keys) { 1895 | static::reportInvalidArgument( 1896 | $message ?: 'Expected list - non-associative array.' 1897 | ); 1898 | } 1899 | } 1900 | 1901 | /** 1902 | * @psalm-pure 1903 | * 1904 | * @psalm-assert non-empty-list $array 1905 | * 1906 | * @param mixed $array 1907 | * @param string $message 1908 | * 1909 | * @throws InvalidArgumentException 1910 | */ 1911 | public static function isNonEmptyList($array, $message = '') 1912 | { 1913 | static::isList($array, $message); 1914 | static::notEmpty($array, $message); 1915 | } 1916 | 1917 | /** 1918 | * @psalm-pure 1919 | * 1920 | * @psalm-template T 1921 | * 1922 | * @psalm-param mixed|array $array 1923 | * 1924 | * @psalm-assert array $array 1925 | * 1926 | * @param mixed $array 1927 | * @param string $message 1928 | * 1929 | * @throws InvalidArgumentException 1930 | */ 1931 | public static function isMap($array, $message = '') 1932 | { 1933 | if ( 1934 | !\is_array($array) 1935 | || \array_keys($array) !== \array_filter(\array_keys($array), '\is_string') 1936 | ) { 1937 | static::reportInvalidArgument( 1938 | $message ?: 'Expected map - associative array with string keys.' 1939 | ); 1940 | } 1941 | } 1942 | 1943 | /** 1944 | * @psalm-pure 1945 | * 1946 | * @psalm-template T 1947 | * 1948 | * @psalm-param mixed|array $array 1949 | * 1950 | * @psalm-assert array $array 1951 | * @psalm-assert !empty $array 1952 | * 1953 | * @param mixed $array 1954 | * @param string $message 1955 | * 1956 | * @throws InvalidArgumentException 1957 | */ 1958 | public static function isNonEmptyMap($array, $message = '') 1959 | { 1960 | static::isMap($array, $message); 1961 | static::notEmpty($array, $message); 1962 | } 1963 | 1964 | /** 1965 | * @psalm-pure 1966 | * 1967 | * @param string $value 1968 | * @param string $message 1969 | * 1970 | * @throws InvalidArgumentException 1971 | */ 1972 | public static function uuid($value, $message = '') 1973 | { 1974 | $value = \str_replace(array('urn:', 'uuid:', '{', '}'), '', $value); 1975 | 1976 | // The nil UUID is special form of UUID that is specified to have all 1977 | // 128 bits set to zero. 1978 | if ('00000000-0000-0000-0000-000000000000' === $value) { 1979 | return; 1980 | } 1981 | 1982 | if (!\preg_match('/^[0-9A-Fa-f]{8}-[0-9A-Fa-f]{4}-[0-9A-Fa-f]{4}-[0-9A-Fa-f]{4}-[0-9A-Fa-f]{12}$/', $value)) { 1983 | static::reportInvalidArgument(\sprintf( 1984 | $message ?: 'Value %s is not a valid UUID.', 1985 | static::valueToString($value) 1986 | )); 1987 | } 1988 | } 1989 | 1990 | /** 1991 | * @psalm-param class-string $class 1992 | * 1993 | * @param Closure $expression 1994 | * @param string $class 1995 | * @param string $message 1996 | * 1997 | * @throws InvalidArgumentException 1998 | */ 1999 | public static function throws(Closure $expression, $class = 'Exception', $message = '') 2000 | { 2001 | static::string($class); 2002 | 2003 | $actual = 'none'; 2004 | 2005 | try { 2006 | $expression(); 2007 | } catch (Exception $e) { 2008 | $actual = \get_class($e); 2009 | if ($e instanceof $class) { 2010 | return; 2011 | } 2012 | } catch (Throwable $e) { 2013 | $actual = \get_class($e); 2014 | if ($e instanceof $class) { 2015 | return; 2016 | } 2017 | } 2018 | 2019 | static::reportInvalidArgument($message ?: \sprintf( 2020 | 'Expected to throw "%s", got "%s"', 2021 | $class, 2022 | $actual 2023 | )); 2024 | } 2025 | 2026 | /** 2027 | * @throws BadMethodCallException 2028 | */ 2029 | public static function __callStatic($name, $arguments) 2030 | { 2031 | if ('nullOr' === \substr($name, 0, 6)) { 2032 | if (null !== $arguments[0]) { 2033 | $method = \lcfirst(\substr($name, 6)); 2034 | \call_user_func_array(array(static::class, $method), $arguments); 2035 | } 2036 | 2037 | return; 2038 | } 2039 | 2040 | if ('all' === \substr($name, 0, 3)) { 2041 | static::isIterable($arguments[0]); 2042 | 2043 | $method = \lcfirst(\substr($name, 3)); 2044 | $args = $arguments; 2045 | 2046 | foreach ($arguments[0] as $entry) { 2047 | $args[0] = $entry; 2048 | 2049 | \call_user_func_array(array(static::class, $method), $args); 2050 | } 2051 | 2052 | return; 2053 | } 2054 | 2055 | throw new BadMethodCallException('No such method: '.$name); 2056 | } 2057 | 2058 | /** 2059 | * @param mixed $value 2060 | * 2061 | * @return string 2062 | */ 2063 | protected static function valueToString($value) 2064 | { 2065 | if (null === $value) { 2066 | return 'null'; 2067 | } 2068 | 2069 | if (true === $value) { 2070 | return 'true'; 2071 | } 2072 | 2073 | if (false === $value) { 2074 | return 'false'; 2075 | } 2076 | 2077 | if (\is_array($value)) { 2078 | return 'array'; 2079 | } 2080 | 2081 | if (\is_object($value)) { 2082 | if (\method_exists($value, '__toString')) { 2083 | return \get_class($value).': '.self::valueToString($value->__toString()); 2084 | } 2085 | 2086 | if ($value instanceof DateTime || $value instanceof DateTimeImmutable) { 2087 | return \get_class($value).': '.self::valueToString($value->format('c')); 2088 | } 2089 | 2090 | if (\function_exists('enum_exists') && \enum_exists(\get_class($value))) { 2091 | return \get_class($value).'::'.$value->name; 2092 | } 2093 | 2094 | return \get_class($value); 2095 | } 2096 | 2097 | if (\is_resource($value)) { 2098 | return 'resource'; 2099 | } 2100 | 2101 | if (\is_string($value)) { 2102 | return '"'.$value.'"'; 2103 | } 2104 | 2105 | return (string) $value; 2106 | } 2107 | 2108 | /** 2109 | * @psalm-pure 2110 | * 2111 | * @param mixed $value 2112 | * 2113 | * @return string 2114 | */ 2115 | protected static function typeToString($value) 2116 | { 2117 | return \is_object($value) ? \get_class($value) : \gettype($value); 2118 | } 2119 | 2120 | protected static function strlen($value) 2121 | { 2122 | if (!\function_exists('mb_detect_encoding')) { 2123 | return \strlen($value); 2124 | } 2125 | 2126 | if (false === $encoding = \mb_detect_encoding($value)) { 2127 | return \strlen($value); 2128 | } 2129 | 2130 | return \mb_strlen($value, $encoding); 2131 | } 2132 | 2133 | /** 2134 | * @param string $message 2135 | * 2136 | * @throws InvalidArgumentException 2137 | * 2138 | * @psalm-pure this method is not supposed to perform side-effects 2139 | * 2140 | * @psalm-return never 2141 | */ 2142 | protected static function reportInvalidArgument($message) 2143 | { 2144 | throw new InvalidArgumentException($message); 2145 | } 2146 | 2147 | private function __construct() 2148 | { 2149 | } 2150 | } 2151 | -------------------------------------------------------------------------------- /src/InvalidArgumentException.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace Webmozart\Assert; 13 | 14 | class InvalidArgumentException extends \InvalidArgumentException 15 | { 16 | } 17 | -------------------------------------------------------------------------------- /tools/php-cs-fixer/composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "require-dev": { 3 | "friendsofphp/php-cs-fixer": "^3.64" 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /tools/phpunit/composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "require-dev": { 3 | "phpunit/phpunit": "^8.5" 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /tools/phpunit/composer.lock: -------------------------------------------------------------------------------- 1 | { 2 | "_readme": [ 3 | "This file locks the dependencies of your project to a known state", 4 | "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", 5 | "This file is @generated automatically" 6 | ], 7 | "content-hash": "4a62d3a5c56e5614bc6122798e246434", 8 | "packages": [], 9 | "packages-dev": [ 10 | { 11 | "name": "doctrine/instantiator", 12 | "version": "1.5.0", 13 | "source": { 14 | "type": "git", 15 | "url": "https://github.com/doctrine/instantiator.git", 16 | "reference": "0a0fa9780f5d4e507415a065172d26a98d02047b" 17 | }, 18 | "dist": { 19 | "type": "zip", 20 | "url": "https://api.github.com/repos/doctrine/instantiator/zipball/0a0fa9780f5d4e507415a065172d26a98d02047b", 21 | "reference": "0a0fa9780f5d4e507415a065172d26a98d02047b", 22 | "shasum": "" 23 | }, 24 | "require": { 25 | "php": "^7.1 || ^8.0" 26 | }, 27 | "require-dev": { 28 | "doctrine/coding-standard": "^9 || ^11", 29 | "ext-pdo": "*", 30 | "ext-phar": "*", 31 | "phpbench/phpbench": "^0.16 || ^1", 32 | "phpstan/phpstan": "^1.4", 33 | "phpstan/phpstan-phpunit": "^1", 34 | "phpunit/phpunit": "^7.5 || ^8.5 || ^9.5", 35 | "vimeo/psalm": "^4.30 || ^5.4" 36 | }, 37 | "type": "library", 38 | "autoload": { 39 | "psr-4": { 40 | "Doctrine\\Instantiator\\": "src/Doctrine/Instantiator/" 41 | } 42 | }, 43 | "notification-url": "https://packagist.org/downloads/", 44 | "license": [ 45 | "MIT" 46 | ], 47 | "authors": [ 48 | { 49 | "name": "Marco Pivetta", 50 | "email": "ocramius@gmail.com", 51 | "homepage": "https://ocramius.github.io/" 52 | } 53 | ], 54 | "description": "A small, lightweight utility to instantiate objects in PHP without invoking their constructors", 55 | "homepage": "https://www.doctrine-project.org/projects/instantiator.html", 56 | "keywords": [ 57 | "constructor", 58 | "instantiate" 59 | ], 60 | "support": { 61 | "issues": "https://github.com/doctrine/instantiator/issues", 62 | "source": "https://github.com/doctrine/instantiator/tree/1.5.0" 63 | }, 64 | "funding": [ 65 | { 66 | "url": "https://www.doctrine-project.org/sponsorship.html", 67 | "type": "custom" 68 | }, 69 | { 70 | "url": "https://www.patreon.com/phpdoctrine", 71 | "type": "patreon" 72 | }, 73 | { 74 | "url": "https://tidelift.com/funding/github/packagist/doctrine%2Finstantiator", 75 | "type": "tidelift" 76 | } 77 | ], 78 | "time": "2022-12-30T00:15:36+00:00" 79 | }, 80 | { 81 | "name": "myclabs/deep-copy", 82 | "version": "1.12.0", 83 | "source": { 84 | "type": "git", 85 | "url": "https://github.com/myclabs/DeepCopy.git", 86 | "reference": "3a6b9a42cd8f8771bd4295d13e1423fa7f3d942c" 87 | }, 88 | "dist": { 89 | "type": "zip", 90 | "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/3a6b9a42cd8f8771bd4295d13e1423fa7f3d942c", 91 | "reference": "3a6b9a42cd8f8771bd4295d13e1423fa7f3d942c", 92 | "shasum": "" 93 | }, 94 | "require": { 95 | "php": "^7.1 || ^8.0" 96 | }, 97 | "conflict": { 98 | "doctrine/collections": "<1.6.8", 99 | "doctrine/common": "<2.13.3 || >=3 <3.2.2" 100 | }, 101 | "require-dev": { 102 | "doctrine/collections": "^1.6.8", 103 | "doctrine/common": "^2.13.3 || ^3.2.2", 104 | "phpspec/prophecy": "^1.10", 105 | "phpunit/phpunit": "^7.5.20 || ^8.5.23 || ^9.5.13" 106 | }, 107 | "type": "library", 108 | "autoload": { 109 | "files": [ 110 | "src/DeepCopy/deep_copy.php" 111 | ], 112 | "psr-4": { 113 | "DeepCopy\\": "src/DeepCopy/" 114 | } 115 | }, 116 | "notification-url": "https://packagist.org/downloads/", 117 | "license": [ 118 | "MIT" 119 | ], 120 | "description": "Create deep copies (clones) of your objects", 121 | "keywords": [ 122 | "clone", 123 | "copy", 124 | "duplicate", 125 | "object", 126 | "object graph" 127 | ], 128 | "support": { 129 | "issues": "https://github.com/myclabs/DeepCopy/issues", 130 | "source": "https://github.com/myclabs/DeepCopy/tree/1.12.0" 131 | }, 132 | "funding": [ 133 | { 134 | "url": "https://tidelift.com/funding/github/packagist/myclabs/deep-copy", 135 | "type": "tidelift" 136 | } 137 | ], 138 | "time": "2024-06-12T14:39:25+00:00" 139 | }, 140 | { 141 | "name": "phar-io/manifest", 142 | "version": "2.0.4", 143 | "source": { 144 | "type": "git", 145 | "url": "https://github.com/phar-io/manifest.git", 146 | "reference": "54750ef60c58e43759730615a392c31c80e23176" 147 | }, 148 | "dist": { 149 | "type": "zip", 150 | "url": "https://api.github.com/repos/phar-io/manifest/zipball/54750ef60c58e43759730615a392c31c80e23176", 151 | "reference": "54750ef60c58e43759730615a392c31c80e23176", 152 | "shasum": "" 153 | }, 154 | "require": { 155 | "ext-dom": "*", 156 | "ext-libxml": "*", 157 | "ext-phar": "*", 158 | "ext-xmlwriter": "*", 159 | "phar-io/version": "^3.0.1", 160 | "php": "^7.2 || ^8.0" 161 | }, 162 | "type": "library", 163 | "extra": { 164 | "branch-alias": { 165 | "dev-master": "2.0.x-dev" 166 | } 167 | }, 168 | "autoload": { 169 | "classmap": [ 170 | "src/" 171 | ] 172 | }, 173 | "notification-url": "https://packagist.org/downloads/", 174 | "license": [ 175 | "BSD-3-Clause" 176 | ], 177 | "authors": [ 178 | { 179 | "name": "Arne Blankerts", 180 | "email": "arne@blankerts.de", 181 | "role": "Developer" 182 | }, 183 | { 184 | "name": "Sebastian Heuer", 185 | "email": "sebastian@phpeople.de", 186 | "role": "Developer" 187 | }, 188 | { 189 | "name": "Sebastian Bergmann", 190 | "email": "sebastian@phpunit.de", 191 | "role": "Developer" 192 | } 193 | ], 194 | "description": "Component for reading phar.io manifest information from a PHP Archive (PHAR)", 195 | "support": { 196 | "issues": "https://github.com/phar-io/manifest/issues", 197 | "source": "https://github.com/phar-io/manifest/tree/2.0.4" 198 | }, 199 | "funding": [ 200 | { 201 | "url": "https://github.com/theseer", 202 | "type": "github" 203 | } 204 | ], 205 | "time": "2024-03-03T12:33:53+00:00" 206 | }, 207 | { 208 | "name": "phar-io/version", 209 | "version": "3.2.1", 210 | "source": { 211 | "type": "git", 212 | "url": "https://github.com/phar-io/version.git", 213 | "reference": "4f7fd7836c6f332bb2933569e566a0d6c4cbed74" 214 | }, 215 | "dist": { 216 | "type": "zip", 217 | "url": "https://api.github.com/repos/phar-io/version/zipball/4f7fd7836c6f332bb2933569e566a0d6c4cbed74", 218 | "reference": "4f7fd7836c6f332bb2933569e566a0d6c4cbed74", 219 | "shasum": "" 220 | }, 221 | "require": { 222 | "php": "^7.2 || ^8.0" 223 | }, 224 | "type": "library", 225 | "autoload": { 226 | "classmap": [ 227 | "src/" 228 | ] 229 | }, 230 | "notification-url": "https://packagist.org/downloads/", 231 | "license": [ 232 | "BSD-3-Clause" 233 | ], 234 | "authors": [ 235 | { 236 | "name": "Arne Blankerts", 237 | "email": "arne@blankerts.de", 238 | "role": "Developer" 239 | }, 240 | { 241 | "name": "Sebastian Heuer", 242 | "email": "sebastian@phpeople.de", 243 | "role": "Developer" 244 | }, 245 | { 246 | "name": "Sebastian Bergmann", 247 | "email": "sebastian@phpunit.de", 248 | "role": "Developer" 249 | } 250 | ], 251 | "description": "Library for handling version information and constraints", 252 | "support": { 253 | "issues": "https://github.com/phar-io/version/issues", 254 | "source": "https://github.com/phar-io/version/tree/3.2.1" 255 | }, 256 | "time": "2022-02-21T01:04:05+00:00" 257 | }, 258 | { 259 | "name": "phpunit/php-code-coverage", 260 | "version": "7.0.17", 261 | "source": { 262 | "type": "git", 263 | "url": "https://github.com/sebastianbergmann/php-code-coverage.git", 264 | "reference": "40a4ed114a4aea5afd6df8d0f0c9cd3033097f66" 265 | }, 266 | "dist": { 267 | "type": "zip", 268 | "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/40a4ed114a4aea5afd6df8d0f0c9cd3033097f66", 269 | "reference": "40a4ed114a4aea5afd6df8d0f0c9cd3033097f66", 270 | "shasum": "" 271 | }, 272 | "require": { 273 | "ext-dom": "*", 274 | "ext-xmlwriter": "*", 275 | "php": ">=7.2", 276 | "phpunit/php-file-iterator": "^2.0.2", 277 | "phpunit/php-text-template": "^1.2.1", 278 | "phpunit/php-token-stream": "^3.1.3 || ^4.0", 279 | "sebastian/code-unit-reverse-lookup": "^1.0.1", 280 | "sebastian/environment": "^4.2.2", 281 | "sebastian/version": "^2.0.1", 282 | "theseer/tokenizer": "^1.1.3" 283 | }, 284 | "require-dev": { 285 | "phpunit/phpunit": "^8.2.2" 286 | }, 287 | "suggest": { 288 | "ext-xdebug": "^2.7.2" 289 | }, 290 | "type": "library", 291 | "extra": { 292 | "branch-alias": { 293 | "dev-master": "7.0-dev" 294 | } 295 | }, 296 | "autoload": { 297 | "classmap": [ 298 | "src/" 299 | ] 300 | }, 301 | "notification-url": "https://packagist.org/downloads/", 302 | "license": [ 303 | "BSD-3-Clause" 304 | ], 305 | "authors": [ 306 | { 307 | "name": "Sebastian Bergmann", 308 | "email": "sebastian@phpunit.de", 309 | "role": "lead" 310 | } 311 | ], 312 | "description": "Library that provides collection, processing, and rendering functionality for PHP code coverage information.", 313 | "homepage": "https://github.com/sebastianbergmann/php-code-coverage", 314 | "keywords": [ 315 | "coverage", 316 | "testing", 317 | "xunit" 318 | ], 319 | "support": { 320 | "issues": "https://github.com/sebastianbergmann/php-code-coverage/issues", 321 | "source": "https://github.com/sebastianbergmann/php-code-coverage/tree/7.0.17" 322 | }, 323 | "funding": [ 324 | { 325 | "url": "https://github.com/sebastianbergmann", 326 | "type": "github" 327 | } 328 | ], 329 | "time": "2024-03-02T06:09:37+00:00" 330 | }, 331 | { 332 | "name": "phpunit/php-file-iterator", 333 | "version": "2.0.6", 334 | "source": { 335 | "type": "git", 336 | "url": "https://github.com/sebastianbergmann/php-file-iterator.git", 337 | "reference": "69deeb8664f611f156a924154985fbd4911eb36b" 338 | }, 339 | "dist": { 340 | "type": "zip", 341 | "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/69deeb8664f611f156a924154985fbd4911eb36b", 342 | "reference": "69deeb8664f611f156a924154985fbd4911eb36b", 343 | "shasum": "" 344 | }, 345 | "require": { 346 | "php": ">=7.1" 347 | }, 348 | "require-dev": { 349 | "phpunit/phpunit": "^8.5" 350 | }, 351 | "type": "library", 352 | "extra": { 353 | "branch-alias": { 354 | "dev-master": "2.0.x-dev" 355 | } 356 | }, 357 | "autoload": { 358 | "classmap": [ 359 | "src/" 360 | ] 361 | }, 362 | "notification-url": "https://packagist.org/downloads/", 363 | "license": [ 364 | "BSD-3-Clause" 365 | ], 366 | "authors": [ 367 | { 368 | "name": "Sebastian Bergmann", 369 | "email": "sebastian@phpunit.de", 370 | "role": "lead" 371 | } 372 | ], 373 | "description": "FilterIterator implementation that filters files based on a list of suffixes.", 374 | "homepage": "https://github.com/sebastianbergmann/php-file-iterator/", 375 | "keywords": [ 376 | "filesystem", 377 | "iterator" 378 | ], 379 | "support": { 380 | "issues": "https://github.com/sebastianbergmann/php-file-iterator/issues", 381 | "source": "https://github.com/sebastianbergmann/php-file-iterator/tree/2.0.6" 382 | }, 383 | "funding": [ 384 | { 385 | "url": "https://github.com/sebastianbergmann", 386 | "type": "github" 387 | } 388 | ], 389 | "time": "2024-03-01T13:39:50+00:00" 390 | }, 391 | { 392 | "name": "phpunit/php-text-template", 393 | "version": "1.2.1", 394 | "source": { 395 | "type": "git", 396 | "url": "https://github.com/sebastianbergmann/php-text-template.git", 397 | "reference": "31f8b717e51d9a2afca6c9f046f5d69fc27c8686" 398 | }, 399 | "dist": { 400 | "type": "zip", 401 | "url": "https://api.github.com/repos/sebastianbergmann/php-text-template/zipball/31f8b717e51d9a2afca6c9f046f5d69fc27c8686", 402 | "reference": "31f8b717e51d9a2afca6c9f046f5d69fc27c8686", 403 | "shasum": "" 404 | }, 405 | "require": { 406 | "php": ">=5.3.3" 407 | }, 408 | "type": "library", 409 | "autoload": { 410 | "classmap": [ 411 | "src/" 412 | ] 413 | }, 414 | "notification-url": "https://packagist.org/downloads/", 415 | "license": [ 416 | "BSD-3-Clause" 417 | ], 418 | "authors": [ 419 | { 420 | "name": "Sebastian Bergmann", 421 | "email": "sebastian@phpunit.de", 422 | "role": "lead" 423 | } 424 | ], 425 | "description": "Simple template engine.", 426 | "homepage": "https://github.com/sebastianbergmann/php-text-template/", 427 | "keywords": [ 428 | "template" 429 | ], 430 | "support": { 431 | "issues": "https://github.com/sebastianbergmann/php-text-template/issues", 432 | "source": "https://github.com/sebastianbergmann/php-text-template/tree/1.2.1" 433 | }, 434 | "time": "2015-06-21T13:50:34+00:00" 435 | }, 436 | { 437 | "name": "phpunit/php-timer", 438 | "version": "2.1.4", 439 | "source": { 440 | "type": "git", 441 | "url": "https://github.com/sebastianbergmann/php-timer.git", 442 | "reference": "a691211e94ff39a34811abd521c31bd5b305b0bb" 443 | }, 444 | "dist": { 445 | "type": "zip", 446 | "url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/a691211e94ff39a34811abd521c31bd5b305b0bb", 447 | "reference": "a691211e94ff39a34811abd521c31bd5b305b0bb", 448 | "shasum": "" 449 | }, 450 | "require": { 451 | "php": ">=7.1" 452 | }, 453 | "require-dev": { 454 | "phpunit/phpunit": "^8.5" 455 | }, 456 | "type": "library", 457 | "extra": { 458 | "branch-alias": { 459 | "dev-master": "2.1-dev" 460 | } 461 | }, 462 | "autoload": { 463 | "classmap": [ 464 | "src/" 465 | ] 466 | }, 467 | "notification-url": "https://packagist.org/downloads/", 468 | "license": [ 469 | "BSD-3-Clause" 470 | ], 471 | "authors": [ 472 | { 473 | "name": "Sebastian Bergmann", 474 | "email": "sebastian@phpunit.de", 475 | "role": "lead" 476 | } 477 | ], 478 | "description": "Utility class for timing", 479 | "homepage": "https://github.com/sebastianbergmann/php-timer/", 480 | "keywords": [ 481 | "timer" 482 | ], 483 | "support": { 484 | "issues": "https://github.com/sebastianbergmann/php-timer/issues", 485 | "source": "https://github.com/sebastianbergmann/php-timer/tree/2.1.4" 486 | }, 487 | "funding": [ 488 | { 489 | "url": "https://github.com/sebastianbergmann", 490 | "type": "github" 491 | } 492 | ], 493 | "time": "2024-03-01T13:42:41+00:00" 494 | }, 495 | { 496 | "name": "phpunit/php-token-stream", 497 | "version": "4.0.4", 498 | "source": { 499 | "type": "git", 500 | "url": "https://github.com/sebastianbergmann/php-token-stream.git", 501 | "reference": "a853a0e183b9db7eed023d7933a858fa1c8d25a3" 502 | }, 503 | "dist": { 504 | "type": "zip", 505 | "url": "https://api.github.com/repos/sebastianbergmann/php-token-stream/zipball/a853a0e183b9db7eed023d7933a858fa1c8d25a3", 506 | "reference": "a853a0e183b9db7eed023d7933a858fa1c8d25a3", 507 | "shasum": "" 508 | }, 509 | "require": { 510 | "ext-tokenizer": "*", 511 | "php": "^7.3 || ^8.0" 512 | }, 513 | "require-dev": { 514 | "phpunit/phpunit": "^9.0" 515 | }, 516 | "type": "library", 517 | "extra": { 518 | "branch-alias": { 519 | "dev-master": "4.0-dev" 520 | } 521 | }, 522 | "autoload": { 523 | "classmap": [ 524 | "src/" 525 | ] 526 | }, 527 | "notification-url": "https://packagist.org/downloads/", 528 | "license": [ 529 | "BSD-3-Clause" 530 | ], 531 | "authors": [ 532 | { 533 | "name": "Sebastian Bergmann", 534 | "email": "sebastian@phpunit.de" 535 | } 536 | ], 537 | "description": "Wrapper around PHP's tokenizer extension.", 538 | "homepage": "https://github.com/sebastianbergmann/php-token-stream/", 539 | "keywords": [ 540 | "tokenizer" 541 | ], 542 | "support": { 543 | "issues": "https://github.com/sebastianbergmann/php-token-stream/issues", 544 | "source": "https://github.com/sebastianbergmann/php-token-stream/tree/master" 545 | }, 546 | "funding": [ 547 | { 548 | "url": "https://github.com/sebastianbergmann", 549 | "type": "github" 550 | } 551 | ], 552 | "abandoned": true, 553 | "time": "2020-08-04T08:28:15+00:00" 554 | }, 555 | { 556 | "name": "phpunit/phpunit", 557 | "version": "8.5.40", 558 | "source": { 559 | "type": "git", 560 | "url": "https://github.com/sebastianbergmann/phpunit.git", 561 | "reference": "48ed828b72c35b38cdddcd9059339734cb06b3a7" 562 | }, 563 | "dist": { 564 | "type": "zip", 565 | "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/48ed828b72c35b38cdddcd9059339734cb06b3a7", 566 | "reference": "48ed828b72c35b38cdddcd9059339734cb06b3a7", 567 | "shasum": "" 568 | }, 569 | "require": { 570 | "doctrine/instantiator": "^1.5.0", 571 | "ext-dom": "*", 572 | "ext-json": "*", 573 | "ext-libxml": "*", 574 | "ext-mbstring": "*", 575 | "ext-xml": "*", 576 | "ext-xmlwriter": "*", 577 | "myclabs/deep-copy": "^1.12.0", 578 | "phar-io/manifest": "^2.0.4", 579 | "phar-io/version": "^3.2.1", 580 | "php": ">=7.2", 581 | "phpunit/php-code-coverage": "^7.0.17", 582 | "phpunit/php-file-iterator": "^2.0.6", 583 | "phpunit/php-text-template": "^1.2.1", 584 | "phpunit/php-timer": "^2.1.4", 585 | "sebastian/comparator": "^3.0.5", 586 | "sebastian/diff": "^3.0.6", 587 | "sebastian/environment": "^4.2.5", 588 | "sebastian/exporter": "^3.1.6", 589 | "sebastian/global-state": "^3.0.5", 590 | "sebastian/object-enumerator": "^3.0.5", 591 | "sebastian/resource-operations": "^2.0.3", 592 | "sebastian/type": "^1.1.5", 593 | "sebastian/version": "^2.0.1" 594 | }, 595 | "suggest": { 596 | "ext-soap": "To be able to generate mocks based on WSDL files", 597 | "ext-xdebug": "PHP extension that provides line coverage as well as branch and path coverage", 598 | "phpunit/php-invoker": "To allow enforcing time limits" 599 | }, 600 | "bin": [ 601 | "phpunit" 602 | ], 603 | "type": "library", 604 | "extra": { 605 | "branch-alias": { 606 | "dev-master": "8.5-dev" 607 | } 608 | }, 609 | "autoload": { 610 | "classmap": [ 611 | "src/" 612 | ] 613 | }, 614 | "notification-url": "https://packagist.org/downloads/", 615 | "license": [ 616 | "BSD-3-Clause" 617 | ], 618 | "authors": [ 619 | { 620 | "name": "Sebastian Bergmann", 621 | "email": "sebastian@phpunit.de", 622 | "role": "lead" 623 | } 624 | ], 625 | "description": "The PHP Unit Testing framework.", 626 | "homepage": "https://phpunit.de/", 627 | "keywords": [ 628 | "phpunit", 629 | "testing", 630 | "xunit" 631 | ], 632 | "support": { 633 | "issues": "https://github.com/sebastianbergmann/phpunit/issues", 634 | "security": "https://github.com/sebastianbergmann/phpunit/security/policy", 635 | "source": "https://github.com/sebastianbergmann/phpunit/tree/8.5.40" 636 | }, 637 | "funding": [ 638 | { 639 | "url": "https://phpunit.de/sponsors.html", 640 | "type": "custom" 641 | }, 642 | { 643 | "url": "https://github.com/sebastianbergmann", 644 | "type": "github" 645 | }, 646 | { 647 | "url": "https://tidelift.com/funding/github/packagist/phpunit/phpunit", 648 | "type": "tidelift" 649 | } 650 | ], 651 | "time": "2024-09-19T10:47:04+00:00" 652 | }, 653 | { 654 | "name": "sebastian/code-unit-reverse-lookup", 655 | "version": "1.0.3", 656 | "source": { 657 | "type": "git", 658 | "url": "https://github.com/sebastianbergmann/code-unit-reverse-lookup.git", 659 | "reference": "92a1a52e86d34cde6caa54f1b5ffa9fda18e5d54" 660 | }, 661 | "dist": { 662 | "type": "zip", 663 | "url": "https://api.github.com/repos/sebastianbergmann/code-unit-reverse-lookup/zipball/92a1a52e86d34cde6caa54f1b5ffa9fda18e5d54", 664 | "reference": "92a1a52e86d34cde6caa54f1b5ffa9fda18e5d54", 665 | "shasum": "" 666 | }, 667 | "require": { 668 | "php": ">=5.6" 669 | }, 670 | "require-dev": { 671 | "phpunit/phpunit": "^8.5" 672 | }, 673 | "type": "library", 674 | "extra": { 675 | "branch-alias": { 676 | "dev-master": "1.0.x-dev" 677 | } 678 | }, 679 | "autoload": { 680 | "classmap": [ 681 | "src/" 682 | ] 683 | }, 684 | "notification-url": "https://packagist.org/downloads/", 685 | "license": [ 686 | "BSD-3-Clause" 687 | ], 688 | "authors": [ 689 | { 690 | "name": "Sebastian Bergmann", 691 | "email": "sebastian@phpunit.de" 692 | } 693 | ], 694 | "description": "Looks up which function or method a line of code belongs to", 695 | "homepage": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/", 696 | "support": { 697 | "issues": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/issues", 698 | "source": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/tree/1.0.3" 699 | }, 700 | "funding": [ 701 | { 702 | "url": "https://github.com/sebastianbergmann", 703 | "type": "github" 704 | } 705 | ], 706 | "time": "2024-03-01T13:45:45+00:00" 707 | }, 708 | { 709 | "name": "sebastian/comparator", 710 | "version": "3.0.5", 711 | "source": { 712 | "type": "git", 713 | "url": "https://github.com/sebastianbergmann/comparator.git", 714 | "reference": "1dc7ceb4a24aede938c7af2a9ed1de09609ca770" 715 | }, 716 | "dist": { 717 | "type": "zip", 718 | "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/1dc7ceb4a24aede938c7af2a9ed1de09609ca770", 719 | "reference": "1dc7ceb4a24aede938c7af2a9ed1de09609ca770", 720 | "shasum": "" 721 | }, 722 | "require": { 723 | "php": ">=7.1", 724 | "sebastian/diff": "^3.0", 725 | "sebastian/exporter": "^3.1" 726 | }, 727 | "require-dev": { 728 | "phpunit/phpunit": "^8.5" 729 | }, 730 | "type": "library", 731 | "extra": { 732 | "branch-alias": { 733 | "dev-master": "3.0-dev" 734 | } 735 | }, 736 | "autoload": { 737 | "classmap": [ 738 | "src/" 739 | ] 740 | }, 741 | "notification-url": "https://packagist.org/downloads/", 742 | "license": [ 743 | "BSD-3-Clause" 744 | ], 745 | "authors": [ 746 | { 747 | "name": "Sebastian Bergmann", 748 | "email": "sebastian@phpunit.de" 749 | }, 750 | { 751 | "name": "Jeff Welch", 752 | "email": "whatthejeff@gmail.com" 753 | }, 754 | { 755 | "name": "Volker Dusch", 756 | "email": "github@wallbash.com" 757 | }, 758 | { 759 | "name": "Bernhard Schussek", 760 | "email": "bschussek@2bepublished.at" 761 | } 762 | ], 763 | "description": "Provides the functionality to compare PHP values for equality", 764 | "homepage": "https://github.com/sebastianbergmann/comparator", 765 | "keywords": [ 766 | "comparator", 767 | "compare", 768 | "equality" 769 | ], 770 | "support": { 771 | "issues": "https://github.com/sebastianbergmann/comparator/issues", 772 | "source": "https://github.com/sebastianbergmann/comparator/tree/3.0.5" 773 | }, 774 | "funding": [ 775 | { 776 | "url": "https://github.com/sebastianbergmann", 777 | "type": "github" 778 | } 779 | ], 780 | "time": "2022-09-14T12:31:48+00:00" 781 | }, 782 | { 783 | "name": "sebastian/diff", 784 | "version": "3.0.6", 785 | "source": { 786 | "type": "git", 787 | "url": "https://github.com/sebastianbergmann/diff.git", 788 | "reference": "98ff311ca519c3aa73ccd3de053bdb377171d7b6" 789 | }, 790 | "dist": { 791 | "type": "zip", 792 | "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/98ff311ca519c3aa73ccd3de053bdb377171d7b6", 793 | "reference": "98ff311ca519c3aa73ccd3de053bdb377171d7b6", 794 | "shasum": "" 795 | }, 796 | "require": { 797 | "php": ">=7.1" 798 | }, 799 | "require-dev": { 800 | "phpunit/phpunit": "^7.5 || ^8.0", 801 | "symfony/process": "^2 || ^3.3 || ^4" 802 | }, 803 | "type": "library", 804 | "extra": { 805 | "branch-alias": { 806 | "dev-master": "3.0-dev" 807 | } 808 | }, 809 | "autoload": { 810 | "classmap": [ 811 | "src/" 812 | ] 813 | }, 814 | "notification-url": "https://packagist.org/downloads/", 815 | "license": [ 816 | "BSD-3-Clause" 817 | ], 818 | "authors": [ 819 | { 820 | "name": "Sebastian Bergmann", 821 | "email": "sebastian@phpunit.de" 822 | }, 823 | { 824 | "name": "Kore Nordmann", 825 | "email": "mail@kore-nordmann.de" 826 | } 827 | ], 828 | "description": "Diff implementation", 829 | "homepage": "https://github.com/sebastianbergmann/diff", 830 | "keywords": [ 831 | "diff", 832 | "udiff", 833 | "unidiff", 834 | "unified diff" 835 | ], 836 | "support": { 837 | "issues": "https://github.com/sebastianbergmann/diff/issues", 838 | "source": "https://github.com/sebastianbergmann/diff/tree/3.0.6" 839 | }, 840 | "funding": [ 841 | { 842 | "url": "https://github.com/sebastianbergmann", 843 | "type": "github" 844 | } 845 | ], 846 | "time": "2024-03-02T06:16:36+00:00" 847 | }, 848 | { 849 | "name": "sebastian/environment", 850 | "version": "4.2.5", 851 | "source": { 852 | "type": "git", 853 | "url": "https://github.com/sebastianbergmann/environment.git", 854 | "reference": "56932f6049a0482853056ffd617c91ffcc754205" 855 | }, 856 | "dist": { 857 | "type": "zip", 858 | "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/56932f6049a0482853056ffd617c91ffcc754205", 859 | "reference": "56932f6049a0482853056ffd617c91ffcc754205", 860 | "shasum": "" 861 | }, 862 | "require": { 863 | "php": ">=7.1" 864 | }, 865 | "require-dev": { 866 | "phpunit/phpunit": "^7.5" 867 | }, 868 | "suggest": { 869 | "ext-posix": "*" 870 | }, 871 | "type": "library", 872 | "extra": { 873 | "branch-alias": { 874 | "dev-master": "4.2-dev" 875 | } 876 | }, 877 | "autoload": { 878 | "classmap": [ 879 | "src/" 880 | ] 881 | }, 882 | "notification-url": "https://packagist.org/downloads/", 883 | "license": [ 884 | "BSD-3-Clause" 885 | ], 886 | "authors": [ 887 | { 888 | "name": "Sebastian Bergmann", 889 | "email": "sebastian@phpunit.de" 890 | } 891 | ], 892 | "description": "Provides functionality to handle HHVM/PHP environments", 893 | "homepage": "http://www.github.com/sebastianbergmann/environment", 894 | "keywords": [ 895 | "Xdebug", 896 | "environment", 897 | "hhvm" 898 | ], 899 | "support": { 900 | "issues": "https://github.com/sebastianbergmann/environment/issues", 901 | "source": "https://github.com/sebastianbergmann/environment/tree/4.2.5" 902 | }, 903 | "funding": [ 904 | { 905 | "url": "https://github.com/sebastianbergmann", 906 | "type": "github" 907 | } 908 | ], 909 | "time": "2024-03-01T13:49:59+00:00" 910 | }, 911 | { 912 | "name": "sebastian/exporter", 913 | "version": "3.1.6", 914 | "source": { 915 | "type": "git", 916 | "url": "https://github.com/sebastianbergmann/exporter.git", 917 | "reference": "1939bc8fd1d39adcfa88c5b35335910869214c56" 918 | }, 919 | "dist": { 920 | "type": "zip", 921 | "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/1939bc8fd1d39adcfa88c5b35335910869214c56", 922 | "reference": "1939bc8fd1d39adcfa88c5b35335910869214c56", 923 | "shasum": "" 924 | }, 925 | "require": { 926 | "php": ">=7.2", 927 | "sebastian/recursion-context": "^3.0" 928 | }, 929 | "require-dev": { 930 | "ext-mbstring": "*", 931 | "phpunit/phpunit": "^8.5" 932 | }, 933 | "type": "library", 934 | "extra": { 935 | "branch-alias": { 936 | "dev-master": "3.1.x-dev" 937 | } 938 | }, 939 | "autoload": { 940 | "classmap": [ 941 | "src/" 942 | ] 943 | }, 944 | "notification-url": "https://packagist.org/downloads/", 945 | "license": [ 946 | "BSD-3-Clause" 947 | ], 948 | "authors": [ 949 | { 950 | "name": "Sebastian Bergmann", 951 | "email": "sebastian@phpunit.de" 952 | }, 953 | { 954 | "name": "Jeff Welch", 955 | "email": "whatthejeff@gmail.com" 956 | }, 957 | { 958 | "name": "Volker Dusch", 959 | "email": "github@wallbash.com" 960 | }, 961 | { 962 | "name": "Adam Harvey", 963 | "email": "aharvey@php.net" 964 | }, 965 | { 966 | "name": "Bernhard Schussek", 967 | "email": "bschussek@gmail.com" 968 | } 969 | ], 970 | "description": "Provides the functionality to export PHP variables for visualization", 971 | "homepage": "http://www.github.com/sebastianbergmann/exporter", 972 | "keywords": [ 973 | "export", 974 | "exporter" 975 | ], 976 | "support": { 977 | "issues": "https://github.com/sebastianbergmann/exporter/issues", 978 | "source": "https://github.com/sebastianbergmann/exporter/tree/3.1.6" 979 | }, 980 | "funding": [ 981 | { 982 | "url": "https://github.com/sebastianbergmann", 983 | "type": "github" 984 | } 985 | ], 986 | "time": "2024-03-02T06:21:38+00:00" 987 | }, 988 | { 989 | "name": "sebastian/global-state", 990 | "version": "3.0.5", 991 | "source": { 992 | "type": "git", 993 | "url": "https://github.com/sebastianbergmann/global-state.git", 994 | "reference": "91c7c47047a971f02de57ed6f040087ef110c5d9" 995 | }, 996 | "dist": { 997 | "type": "zip", 998 | "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/91c7c47047a971f02de57ed6f040087ef110c5d9", 999 | "reference": "91c7c47047a971f02de57ed6f040087ef110c5d9", 1000 | "shasum": "" 1001 | }, 1002 | "require": { 1003 | "php": ">=7.2", 1004 | "sebastian/object-reflector": "^1.1.1", 1005 | "sebastian/recursion-context": "^3.0" 1006 | }, 1007 | "require-dev": { 1008 | "ext-dom": "*", 1009 | "phpunit/phpunit": "^8.0" 1010 | }, 1011 | "suggest": { 1012 | "ext-uopz": "*" 1013 | }, 1014 | "type": "library", 1015 | "extra": { 1016 | "branch-alias": { 1017 | "dev-master": "3.0-dev" 1018 | } 1019 | }, 1020 | "autoload": { 1021 | "classmap": [ 1022 | "src/" 1023 | ] 1024 | }, 1025 | "notification-url": "https://packagist.org/downloads/", 1026 | "license": [ 1027 | "BSD-3-Clause" 1028 | ], 1029 | "authors": [ 1030 | { 1031 | "name": "Sebastian Bergmann", 1032 | "email": "sebastian@phpunit.de" 1033 | } 1034 | ], 1035 | "description": "Snapshotting of global state", 1036 | "homepage": "http://www.github.com/sebastianbergmann/global-state", 1037 | "keywords": [ 1038 | "global state" 1039 | ], 1040 | "support": { 1041 | "issues": "https://github.com/sebastianbergmann/global-state/issues", 1042 | "source": "https://github.com/sebastianbergmann/global-state/tree/3.0.5" 1043 | }, 1044 | "funding": [ 1045 | { 1046 | "url": "https://github.com/sebastianbergmann", 1047 | "type": "github" 1048 | } 1049 | ], 1050 | "time": "2024-03-02T06:13:16+00:00" 1051 | }, 1052 | { 1053 | "name": "sebastian/object-enumerator", 1054 | "version": "3.0.5", 1055 | "source": { 1056 | "type": "git", 1057 | "url": "https://github.com/sebastianbergmann/object-enumerator.git", 1058 | "reference": "ac5b293dba925751b808e02923399fb44ff0d541" 1059 | }, 1060 | "dist": { 1061 | "type": "zip", 1062 | "url": "https://api.github.com/repos/sebastianbergmann/object-enumerator/zipball/ac5b293dba925751b808e02923399fb44ff0d541", 1063 | "reference": "ac5b293dba925751b808e02923399fb44ff0d541", 1064 | "shasum": "" 1065 | }, 1066 | "require": { 1067 | "php": ">=7.0", 1068 | "sebastian/object-reflector": "^1.1.1", 1069 | "sebastian/recursion-context": "^3.0" 1070 | }, 1071 | "require-dev": { 1072 | "phpunit/phpunit": "^6.0" 1073 | }, 1074 | "type": "library", 1075 | "extra": { 1076 | "branch-alias": { 1077 | "dev-master": "3.0.x-dev" 1078 | } 1079 | }, 1080 | "autoload": { 1081 | "classmap": [ 1082 | "src/" 1083 | ] 1084 | }, 1085 | "notification-url": "https://packagist.org/downloads/", 1086 | "license": [ 1087 | "BSD-3-Clause" 1088 | ], 1089 | "authors": [ 1090 | { 1091 | "name": "Sebastian Bergmann", 1092 | "email": "sebastian@phpunit.de" 1093 | } 1094 | ], 1095 | "description": "Traverses array structures and object graphs to enumerate all referenced objects", 1096 | "homepage": "https://github.com/sebastianbergmann/object-enumerator/", 1097 | "support": { 1098 | "issues": "https://github.com/sebastianbergmann/object-enumerator/issues", 1099 | "source": "https://github.com/sebastianbergmann/object-enumerator/tree/3.0.5" 1100 | }, 1101 | "funding": [ 1102 | { 1103 | "url": "https://github.com/sebastianbergmann", 1104 | "type": "github" 1105 | } 1106 | ], 1107 | "time": "2024-03-01T13:54:02+00:00" 1108 | }, 1109 | { 1110 | "name": "sebastian/object-reflector", 1111 | "version": "1.1.3", 1112 | "source": { 1113 | "type": "git", 1114 | "url": "https://github.com/sebastianbergmann/object-reflector.git", 1115 | "reference": "1d439c229e61f244ff1f211e5c99737f90c67def" 1116 | }, 1117 | "dist": { 1118 | "type": "zip", 1119 | "url": "https://api.github.com/repos/sebastianbergmann/object-reflector/zipball/1d439c229e61f244ff1f211e5c99737f90c67def", 1120 | "reference": "1d439c229e61f244ff1f211e5c99737f90c67def", 1121 | "shasum": "" 1122 | }, 1123 | "require": { 1124 | "php": ">=7.0" 1125 | }, 1126 | "require-dev": { 1127 | "phpunit/phpunit": "^6.0" 1128 | }, 1129 | "type": "library", 1130 | "extra": { 1131 | "branch-alias": { 1132 | "dev-master": "1.1-dev" 1133 | } 1134 | }, 1135 | "autoload": { 1136 | "classmap": [ 1137 | "src/" 1138 | ] 1139 | }, 1140 | "notification-url": "https://packagist.org/downloads/", 1141 | "license": [ 1142 | "BSD-3-Clause" 1143 | ], 1144 | "authors": [ 1145 | { 1146 | "name": "Sebastian Bergmann", 1147 | "email": "sebastian@phpunit.de" 1148 | } 1149 | ], 1150 | "description": "Allows reflection of object attributes, including inherited and non-public ones", 1151 | "homepage": "https://github.com/sebastianbergmann/object-reflector/", 1152 | "support": { 1153 | "issues": "https://github.com/sebastianbergmann/object-reflector/issues", 1154 | "source": "https://github.com/sebastianbergmann/object-reflector/tree/1.1.3" 1155 | }, 1156 | "funding": [ 1157 | { 1158 | "url": "https://github.com/sebastianbergmann", 1159 | "type": "github" 1160 | } 1161 | ], 1162 | "time": "2024-03-01T13:56:04+00:00" 1163 | }, 1164 | { 1165 | "name": "sebastian/recursion-context", 1166 | "version": "3.0.2", 1167 | "source": { 1168 | "type": "git", 1169 | "url": "https://github.com/sebastianbergmann/recursion-context.git", 1170 | "reference": "9bfd3c6f1f08c026f542032dfb42813544f7d64c" 1171 | }, 1172 | "dist": { 1173 | "type": "zip", 1174 | "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/9bfd3c6f1f08c026f542032dfb42813544f7d64c", 1175 | "reference": "9bfd3c6f1f08c026f542032dfb42813544f7d64c", 1176 | "shasum": "" 1177 | }, 1178 | "require": { 1179 | "php": ">=7.0" 1180 | }, 1181 | "require-dev": { 1182 | "phpunit/phpunit": "^6.0" 1183 | }, 1184 | "type": "library", 1185 | "extra": { 1186 | "branch-alias": { 1187 | "dev-master": "3.0.x-dev" 1188 | } 1189 | }, 1190 | "autoload": { 1191 | "classmap": [ 1192 | "src/" 1193 | ] 1194 | }, 1195 | "notification-url": "https://packagist.org/downloads/", 1196 | "license": [ 1197 | "BSD-3-Clause" 1198 | ], 1199 | "authors": [ 1200 | { 1201 | "name": "Sebastian Bergmann", 1202 | "email": "sebastian@phpunit.de" 1203 | }, 1204 | { 1205 | "name": "Jeff Welch", 1206 | "email": "whatthejeff@gmail.com" 1207 | }, 1208 | { 1209 | "name": "Adam Harvey", 1210 | "email": "aharvey@php.net" 1211 | } 1212 | ], 1213 | "description": "Provides functionality to recursively process PHP variables", 1214 | "homepage": "http://www.github.com/sebastianbergmann/recursion-context", 1215 | "support": { 1216 | "issues": "https://github.com/sebastianbergmann/recursion-context/issues", 1217 | "source": "https://github.com/sebastianbergmann/recursion-context/tree/3.0.2" 1218 | }, 1219 | "funding": [ 1220 | { 1221 | "url": "https://github.com/sebastianbergmann", 1222 | "type": "github" 1223 | } 1224 | ], 1225 | "time": "2024-03-01T14:07:30+00:00" 1226 | }, 1227 | { 1228 | "name": "sebastian/resource-operations", 1229 | "version": "2.0.3", 1230 | "source": { 1231 | "type": "git", 1232 | "url": "https://github.com/sebastianbergmann/resource-operations.git", 1233 | "reference": "72a7f7674d053d548003b16ff5a106e7e0e06eee" 1234 | }, 1235 | "dist": { 1236 | "type": "zip", 1237 | "url": "https://api.github.com/repos/sebastianbergmann/resource-operations/zipball/72a7f7674d053d548003b16ff5a106e7e0e06eee", 1238 | "reference": "72a7f7674d053d548003b16ff5a106e7e0e06eee", 1239 | "shasum": "" 1240 | }, 1241 | "require": { 1242 | "php": ">=7.1" 1243 | }, 1244 | "type": "library", 1245 | "extra": { 1246 | "branch-alias": { 1247 | "dev-master": "2.0-dev" 1248 | } 1249 | }, 1250 | "autoload": { 1251 | "classmap": [ 1252 | "src/" 1253 | ] 1254 | }, 1255 | "notification-url": "https://packagist.org/downloads/", 1256 | "license": [ 1257 | "BSD-3-Clause" 1258 | ], 1259 | "authors": [ 1260 | { 1261 | "name": "Sebastian Bergmann", 1262 | "email": "sebastian@phpunit.de" 1263 | } 1264 | ], 1265 | "description": "Provides a list of PHP built-in functions that operate on resources", 1266 | "homepage": "https://www.github.com/sebastianbergmann/resource-operations", 1267 | "support": { 1268 | "source": "https://github.com/sebastianbergmann/resource-operations/tree/2.0.3" 1269 | }, 1270 | "funding": [ 1271 | { 1272 | "url": "https://github.com/sebastianbergmann", 1273 | "type": "github" 1274 | } 1275 | ], 1276 | "time": "2024-03-01T13:59:09+00:00" 1277 | }, 1278 | { 1279 | "name": "sebastian/type", 1280 | "version": "1.1.5", 1281 | "source": { 1282 | "type": "git", 1283 | "url": "https://github.com/sebastianbergmann/type.git", 1284 | "reference": "18f071c3a29892b037d35e6b20ddf3ea39b42874" 1285 | }, 1286 | "dist": { 1287 | "type": "zip", 1288 | "url": "https://api.github.com/repos/sebastianbergmann/type/zipball/18f071c3a29892b037d35e6b20ddf3ea39b42874", 1289 | "reference": "18f071c3a29892b037d35e6b20ddf3ea39b42874", 1290 | "shasum": "" 1291 | }, 1292 | "require": { 1293 | "php": ">=7.2" 1294 | }, 1295 | "require-dev": { 1296 | "phpunit/phpunit": "^8.2" 1297 | }, 1298 | "type": "library", 1299 | "extra": { 1300 | "branch-alias": { 1301 | "dev-master": "1.1-dev" 1302 | } 1303 | }, 1304 | "autoload": { 1305 | "classmap": [ 1306 | "src/" 1307 | ] 1308 | }, 1309 | "notification-url": "https://packagist.org/downloads/", 1310 | "license": [ 1311 | "BSD-3-Clause" 1312 | ], 1313 | "authors": [ 1314 | { 1315 | "name": "Sebastian Bergmann", 1316 | "email": "sebastian@phpunit.de", 1317 | "role": "lead" 1318 | } 1319 | ], 1320 | "description": "Collection of value objects that represent the types of the PHP type system", 1321 | "homepage": "https://github.com/sebastianbergmann/type", 1322 | "support": { 1323 | "issues": "https://github.com/sebastianbergmann/type/issues", 1324 | "source": "https://github.com/sebastianbergmann/type/tree/1.1.5" 1325 | }, 1326 | "funding": [ 1327 | { 1328 | "url": "https://github.com/sebastianbergmann", 1329 | "type": "github" 1330 | } 1331 | ], 1332 | "time": "2024-03-01T14:04:07+00:00" 1333 | }, 1334 | { 1335 | "name": "sebastian/version", 1336 | "version": "2.0.1", 1337 | "source": { 1338 | "type": "git", 1339 | "url": "https://github.com/sebastianbergmann/version.git", 1340 | "reference": "99732be0ddb3361e16ad77b68ba41efc8e979019" 1341 | }, 1342 | "dist": { 1343 | "type": "zip", 1344 | "url": "https://api.github.com/repos/sebastianbergmann/version/zipball/99732be0ddb3361e16ad77b68ba41efc8e979019", 1345 | "reference": "99732be0ddb3361e16ad77b68ba41efc8e979019", 1346 | "shasum": "" 1347 | }, 1348 | "require": { 1349 | "php": ">=5.6" 1350 | }, 1351 | "type": "library", 1352 | "extra": { 1353 | "branch-alias": { 1354 | "dev-master": "2.0.x-dev" 1355 | } 1356 | }, 1357 | "autoload": { 1358 | "classmap": [ 1359 | "src/" 1360 | ] 1361 | }, 1362 | "notification-url": "https://packagist.org/downloads/", 1363 | "license": [ 1364 | "BSD-3-Clause" 1365 | ], 1366 | "authors": [ 1367 | { 1368 | "name": "Sebastian Bergmann", 1369 | "email": "sebastian@phpunit.de", 1370 | "role": "lead" 1371 | } 1372 | ], 1373 | "description": "Library that helps with managing the version number of Git-hosted PHP projects", 1374 | "homepage": "https://github.com/sebastianbergmann/version", 1375 | "support": { 1376 | "issues": "https://github.com/sebastianbergmann/version/issues", 1377 | "source": "https://github.com/sebastianbergmann/version/tree/master" 1378 | }, 1379 | "time": "2016-10-03T07:35:21+00:00" 1380 | }, 1381 | { 1382 | "name": "theseer/tokenizer", 1383 | "version": "1.2.3", 1384 | "source": { 1385 | "type": "git", 1386 | "url": "https://github.com/theseer/tokenizer.git", 1387 | "reference": "737eda637ed5e28c3413cb1ebe8bb52cbf1ca7a2" 1388 | }, 1389 | "dist": { 1390 | "type": "zip", 1391 | "url": "https://api.github.com/repos/theseer/tokenizer/zipball/737eda637ed5e28c3413cb1ebe8bb52cbf1ca7a2", 1392 | "reference": "737eda637ed5e28c3413cb1ebe8bb52cbf1ca7a2", 1393 | "shasum": "" 1394 | }, 1395 | "require": { 1396 | "ext-dom": "*", 1397 | "ext-tokenizer": "*", 1398 | "ext-xmlwriter": "*", 1399 | "php": "^7.2 || ^8.0" 1400 | }, 1401 | "type": "library", 1402 | "autoload": { 1403 | "classmap": [ 1404 | "src/" 1405 | ] 1406 | }, 1407 | "notification-url": "https://packagist.org/downloads/", 1408 | "license": [ 1409 | "BSD-3-Clause" 1410 | ], 1411 | "authors": [ 1412 | { 1413 | "name": "Arne Blankerts", 1414 | "email": "arne@blankerts.de", 1415 | "role": "Developer" 1416 | } 1417 | ], 1418 | "description": "A small library for converting tokenized PHP source code into XML and potentially other formats", 1419 | "support": { 1420 | "issues": "https://github.com/theseer/tokenizer/issues", 1421 | "source": "https://github.com/theseer/tokenizer/tree/1.2.3" 1422 | }, 1423 | "funding": [ 1424 | { 1425 | "url": "https://github.com/theseer", 1426 | "type": "github" 1427 | } 1428 | ], 1429 | "time": "2024-03-03T12:36:25+00:00" 1430 | } 1431 | ], 1432 | "aliases": [], 1433 | "minimum-stability": "stable", 1434 | "stability-flags": {}, 1435 | "prefer-stable": false, 1436 | "prefer-lowest": false, 1437 | "platform": {}, 1438 | "platform-dev": {}, 1439 | "plugin-api-version": "2.6.0" 1440 | } 1441 | -------------------------------------------------------------------------------- /tools/psalm/composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "require-dev": { 3 | "vimeo/psalm": "^4.6.1" 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /tools/roave-bc-check/composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "require-dev": { 3 | "roave/backward-compatibility-check": "^8.10" 4 | } 5 | } 6 | --------------------------------------------------------------------------------