├── .scrutinizer.yml ├── .gitignore ├── .travis.yml ├── phpspec.yml.dist ├── src ├── Exception │ ├── MissingPathException.php │ ├── JsonIncludesException.php │ ├── JsonEqualityException.php │ ├── PathMatchException.php │ ├── JsonSizeException.php │ ├── JsonTypeException.php │ └── MatchException.php ├── JsonMatcherFactory.php ├── Helper │ └── JsonHelper.php └── JsonMatcher.php ├── composer.json ├── .php_cs ├── spec ├── Helper │ └── JsonHelperSpec.php └── JsonMatcherSpec.php ├── README.md └── composer.lock /.scrutinizer.yml: -------------------------------------------------------------------------------- 1 | tools: 2 | external_code_coverage: true -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /.idea 2 | /*.iml 3 | .php_cs.cache 4 | /vendor 5 | /coverage 6 | /bin 7 | coverage.xml 8 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: php 2 | 3 | php: 4 | - 7.2 5 | - 7.3 6 | - 7.4 7 | 8 | before_script: 9 | - composer install 10 | 11 | script: 12 | - phpdbg -qrr bin/phpspec run 13 | - ./bin/php-cs-fixer fix --dry-run 14 | 15 | -------------------------------------------------------------------------------- /phpspec.yml.dist: -------------------------------------------------------------------------------- 1 | --- 2 | suites: 3 | event_suite: 4 | namespace: Fesor\JsonMatcher 5 | psr4_prefix: Fesor\JsonMatcher 6 | code_coverage: 7 | format: 8 | - clover 9 | output: 10 | clover: coverage.xml 11 | extensions: 12 | FriendsOfPhpSpec\PhpSpec\CodeCoverage\CodeCoverageExtension: ~ 13 | -------------------------------------------------------------------------------- /src/Exception/MissingPathException.php: -------------------------------------------------------------------------------- 1 | message = sprintf('Path `%s` is not exists for given JSON', $path); 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /src/Exception/JsonIncludesException.php: -------------------------------------------------------------------------------- 1 | =7.2.0" 17 | }, 18 | "require-dev": { 19 | "phpspec/phpspec": "^6.1", 20 | "friends-of-phpspec/phpspec-code-coverage": "^4.3", 21 | "friendsofphp/php-cs-fixer": "^2.16" 22 | }, 23 | "config": { 24 | "bin-dir": "bin" 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/Exception/JsonSizeException.php: -------------------------------------------------------------------------------- 1 | message = $message; 15 | } 16 | 17 | /** 18 | * @return string 19 | */ 20 | protected static function getAt(array $options) 21 | { 22 | if (empty($options[JsonMatcher::OPTION_PATH])) { 23 | return ''; 24 | } 25 | 26 | return sprintf(' at \'%s\'', $options[JsonMatcher::OPTION_PATH]); 27 | } 28 | 29 | /** 30 | * @return bool 31 | */ 32 | protected static function isPositive(array $options) 33 | { 34 | return empty($options[JsonMatcher::OPTION_NEGATIVE]); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /src/JsonMatcherFactory.php: -------------------------------------------------------------------------------- 1 | jsonHelper = $jsonHelper; 22 | $this->excludedKeys = $excludedKeys; 23 | } 24 | 25 | /** 26 | * Creates instance of matcher with given subject. 27 | * 28 | * @param string $subject 29 | * 30 | * @return JsonMatcher 31 | */ 32 | public function create($subject) 33 | { 34 | $matcher = new JsonMatcher($this->jsonHelper, $this->excludedKeys); 35 | 36 | return $matcher->setSubject($subject); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /.php_cs: -------------------------------------------------------------------------------- 1 | in(__DIR__ . '/src') 5 | ->in(__DIR__ . '/spec') 6 | ->files() 7 | ->name('*.php'); 8 | 9 | $rules = [ 10 | '@Symfony' => true, 11 | 'blank_line_before_statement' => false, 12 | 'phpdoc_types_order' => false, 13 | 'increment_style' => false, 14 | 'standardize_increment' => false, 15 | 'array_syntax' => ['syntax' => 'short'], 16 | 'no_superfluous_phpdoc_tags' => true, 17 | 'no_superfluous_elseif' => true, 18 | 'array_indentation' => true, 19 | 'method_chaining_indentation' => true, 20 | 'no_unused_imports' => true, 21 | 'no_extra_consecutive_blank_lines' => ['use'], 22 | 'php_unit_namespaced' => ['target' => 'newest'], 23 | 'php_unit_expectation' => true, 24 | 'concat_space' => false, 25 | ]; 26 | 27 | return PhpCsFixer\Config::create() 28 | ->setRules($rules) 29 | ->setRiskyAllowed(true) 30 | ->setFinder($finder); 31 | -------------------------------------------------------------------------------- /spec/Helper/JsonHelperSpec.php: -------------------------------------------------------------------------------- 1 | json = ['spec']; 14 | $this->parse('{"json":["spec"]}')->shouldBeLike($result); 15 | } 16 | 17 | public function it_parses_JSON_values() 18 | { 19 | $this->parse('"json_spec"')->shouldBe('json_spec'); 20 | $this->parse('10')->shouldBe(10); 21 | $this->parse('null')->shouldBe(null); 22 | } 23 | 24 | public function it_raises_a_parser_error_for_invalid_JSON() 25 | { 26 | $this->shouldThrow()->duringParse('json_spec'); 27 | } 28 | 29 | public function it_parses_at_a_path_if_given() 30 | { 31 | $json = '{"json": ["spec"]}'; 32 | $this->parse($json, 'json')->shouldBeLike(['spec']); 33 | $this->parse($json, 'json/0')->shouldBe('spec'); 34 | } 35 | 36 | public function it_raises_an_error_for_a_missing_path() 37 | { 38 | $json = '{"json": ["spec"]}'; 39 | $this->shouldThrow( 40 | new MissingPathException('json/1') 41 | )->duringParse($json, 'json/1'); 42 | } 43 | 44 | public function it_parses_at_a_numeric_string_path() 45 | { 46 | $json = '{"1": "json"}'; 47 | $this->parse($json, '1')->shouldBe('json'); 48 | } 49 | 50 | public function it_correctly_validate_json_value() 51 | { 52 | $this->isValid('"json_spec"')->shouldBe(true); 53 | $this->isValid('json_spec')->shouldBe(false); 54 | } 55 | 56 | public function it_normalize_json() 57 | { 58 | $normalizedJson = <<normalize('{"laser":{"lemon": "orange", "banana": "watermelon"},"json":"spec"}')->shouldBe(rtrim($normalizedJson)); 69 | } 70 | 71 | public function it_normalize_json_value() 72 | { 73 | $this->normalize('1e+1')->shouldBe('10'); 74 | } 75 | 76 | public function it_normalizes_at_a_path() 77 | { 78 | $this->normalize('{"json":["spec"]}', 'json/0')->shouldBe('"spec"'); 79 | } 80 | 81 | public function it_accept_a_json_value() 82 | { 83 | $this->normalize('1e+1')->shouldBe('10'); 84 | } 85 | 86 | public function it_normalizes_a_json_value() 87 | { 88 | $this->normalize('"json_spec"')->shouldBe('"json_spec"'); 89 | } 90 | 91 | public function it_does_not_change_collection_order() 92 | { 93 | $normalizedJson = <<generateNormalizedJson(['spec', 'json'])->shouldBe(rtrim($normalizedJson)); 101 | } 102 | 103 | public function it_generates_a_normalized_json_document() 104 | { 105 | $normalizedJson = <<generateNormalizedJson((object) ['json' => ['spec']])->shouldBe(rtrim($normalizedJson)); 113 | } 114 | 115 | public function it_should_exclude_keys() 116 | { 117 | $data = (object) [ 118 | 'id' => 1, 119 | 'collection' => [ 120 | (object) [ 121 | 'id' => 1, 122 | 'json' => 'spec', 123 | ], 124 | ], 125 | ]; 126 | 127 | $this->excludeKeys($data, ['id'])->shouldBeLike((object) [ 128 | 'collection' => [ 129 | (object) [ 130 | 'json' => 'spec', 131 | ], 132 | ], 133 | ]); 134 | } 135 | 136 | public function it_checks_is_collection_includes_json() 137 | { 138 | $this->isIncludes(['json'], '"json"')->shouldBe(true); 139 | $this->isIncludes(['spec'], '"json"')->shouldBe(false); 140 | } 141 | 142 | public function it_checks_is_json_string_includes_another_json_string() 143 | { 144 | $this->isIncludes('json', '"json"')->shouldBe(true); 145 | $this->isIncludes('json_spec', '"json"')->shouldBe(true); 146 | $this->isIncludes('spec', '"json"')->shouldBe(false); 147 | } 148 | 149 | public function it_checks_is_json_contains_in_some_property() 150 | { 151 | $obj = (object) [ 152 | 'test' => (object) [ 153 | 'key' => 'value', 154 | ], 155 | ]; 156 | 157 | $needle = <<isIncludes($obj, $needle)->shouldBe(true); 169 | $this->isIncludes($obj, $falseNeedle)->shouldBe(false); 170 | } 171 | 172 | public function it_checks_for_inclusions_recursively() 173 | { 174 | $obj = (object) [ 175 | 'test' => (object) [ 176 | 'key' => ['value', 'find me'], 177 | ], 178 | ]; 179 | 180 | $this->isIncludes($obj, '"find"')->shouldBe(true); 181 | $this->isIncludes($obj, '"find me"')->shouldBe(true); 182 | $this->isIncludes($obj, '"not find me"')->shouldBe(false); 183 | } 184 | } 185 | -------------------------------------------------------------------------------- /src/Helper/JsonHelper.php: -------------------------------------------------------------------------------- 1 | parseJson($json); 21 | 22 | if (null === $path) { 23 | return $data; 24 | } 25 | 26 | return $this->getAtPath($data, $path); 27 | } 28 | 29 | /** 30 | * Checks is given JSON string is valid or not. 31 | * 32 | * @param string $json 33 | * 34 | * @return bool 35 | */ 36 | public function isValid($json) 37 | { 38 | try { 39 | $this->parseJson($json); 40 | } catch (\InvalidArgumentException $e) { 41 | return false; 42 | } 43 | 44 | return true; 45 | } 46 | 47 | /** 48 | * Checks is given JSON contains somewhere in. 49 | * 50 | * @param mixed $haystack contains parsed JSON value 51 | * @param string $needle 52 | * 53 | * @return bool 54 | */ 55 | public function isIncludes($haystack, $needle) 56 | { 57 | $parsedJson = $this->parse($needle); 58 | $normalizedData = $this->generateNormalizedJson($haystack); 59 | if (!is_object($haystack) && !is_array($haystack)) { 60 | if (is_string($haystack) && is_string($parsedJson)) { 61 | return false !== strpos($haystack, $parsedJson); 62 | } 63 | } 64 | 65 | if ($normalizedData === $needle) { 66 | return true; 67 | } 68 | 69 | if (is_object($haystack)) { 70 | $haystack = get_object_vars($haystack); 71 | } 72 | 73 | if (is_array($haystack)) { 74 | foreach ($haystack as $value) { 75 | if ($this->isIncludes($value, $needle)) { 76 | return true; 77 | } 78 | } 79 | } 80 | 81 | return false; 82 | } 83 | 84 | /** 85 | * @param $json 86 | * @param null $path 87 | * 88 | * @return string 89 | */ 90 | public function normalize($json, $path = null) 91 | { 92 | return $this->generateNormalizedJson($this->parse($json, $path)); 93 | } 94 | 95 | /** 96 | * @return string 97 | */ 98 | public function generateNormalizedJson($data) 99 | { 100 | return rtrim(json_encode( 101 | $this->sortObjectKeys($data), 102 | JSON_PRETTY_PRINT 103 | )); 104 | } 105 | 106 | /** 107 | * Recursively removes specific keys from. 108 | * 109 | * @param $data 110 | * @param array|null excludedKeys 111 | */ 112 | public function excludeKeys($data, array $excludedKeys = []) 113 | { 114 | if (is_object($data)) { 115 | $object = new \stdClass(); 116 | foreach (get_object_vars($data) as $key => $value) { 117 | if (in_array($key, $excludedKeys)) { 118 | continue; 119 | } 120 | $object->$key = $this->excludeKeys($value, $excludedKeys); 121 | } 122 | 123 | return $object; 124 | } 125 | 126 | if (is_array($data)) { 127 | return array_map(function ($data) use ($excludedKeys) { 128 | return $this->excludeKeys($data, $excludedKeys); 129 | }, $data); 130 | } 131 | 132 | return $data; 133 | } 134 | 135 | /** 136 | * Get data by given JSON path. 137 | * 138 | * @param string $path 139 | */ 140 | private function getAtPath($data, $path) 141 | { 142 | $pathSegments = explode('/', trim($path, '/')); 143 | foreach ($pathSegments as $key) { 144 | if ($data instanceof \stdClass && property_exists($data, $key)) { 145 | $data = $data->$key; 146 | } elseif (is_array($data) && is_numeric($key) && array_key_exists((int) $key, $data)) { 147 | $data = $data[$key]; 148 | } else { 149 | throw new MissingPathException($path); 150 | } 151 | } 152 | 153 | return $data; 154 | } 155 | 156 | /** 157 | * Recursively sorts objects keys. 158 | * 159 | * @param $data 160 | * 161 | * @return array|object 162 | */ 163 | private function sortObjectKeys($data) 164 | { 165 | if (!is_array($data) && !is_object($data)) { 166 | return $data; 167 | } 168 | 169 | $orderedData = $data; 170 | if (is_object($data)) { 171 | $orderedData = get_object_vars($data); 172 | ksort($orderedData); 173 | } 174 | 175 | foreach ($orderedData as &$value) { 176 | $value = $this->sortObjectKeys($value); 177 | } 178 | 179 | return is_object($data) ? 180 | (object) $orderedData : $orderedData; 181 | } 182 | 183 | /** 184 | * @param string $json 185 | */ 186 | private function parseJson($json) 187 | { 188 | $json = json_decode($json); 189 | if (JSON_ERROR_NONE !== json_last_error()) { 190 | throw new \InvalidArgumentException('Invalid JSON'); 191 | } 192 | 193 | return $json; 194 | } 195 | } 196 | -------------------------------------------------------------------------------- /src/JsonMatcher.php: -------------------------------------------------------------------------------- 1 | jsonHelper = $jsonHelper; 47 | $this->excludeKeys = $excludeKeys; 48 | } 49 | 50 | /** 51 | * Named constructor for simplify usage. 52 | * 53 | * @param string $subject 54 | * 55 | * @return JsonMatcher 56 | */ 57 | public static function create($subject, array $excludedKeys = ['id']) 58 | { 59 | $matcher = new JsonMatcher(new JsonHelper(), $excludedKeys); 60 | $matcher->setSubject($subject); 61 | 62 | return $matcher; 63 | } 64 | 65 | /** 66 | * Checks is given JSON equal to another one. 67 | * 68 | * @param string $expected 69 | * 70 | * @return $this 71 | */ 72 | public function equal($expected, array $options = []) 73 | { 74 | $actual = $this->scrub($this->subject, $options); 75 | $expected = $this->scrub($expected, array_diff_key( 76 | // we should pass all options except `path` 77 | $options, [static::OPTION_PATH => null] 78 | )); 79 | 80 | if ($this->isPositive($options) ^ $actual === $expected) { 81 | throw JsonEqualityException::create($options); 82 | } 83 | 84 | return $this; 85 | } 86 | 87 | /** 88 | * Checks that given path exists in JSON. 89 | * 90 | * @param string|null $path 91 | * 92 | * @return $this 93 | */ 94 | public function hasPath($path, array $options = []) 95 | { 96 | // get base path 97 | $basePath = $this->getPath($options); 98 | $path = ltrim($basePath . '/' . $path, '/'); 99 | $pathExists = true; 100 | try { 101 | $this->jsonHelper->parse($this->subject, $path); 102 | } catch (MissingPathException $e) { 103 | $pathExists = false; 104 | } 105 | 106 | if ($this->isPositive($options) ^ $pathExists) { 107 | throw new PathMatchException($path, $options); 108 | } 109 | 110 | return $this; 111 | } 112 | 113 | /** 114 | * Checks that given JSON have exact amount of items. 115 | * 116 | * @param int $expectedSize 117 | * 118 | * @return $this 119 | */ 120 | public function hasSize($expectedSize, array $options = []) 121 | { 122 | $data = $this->jsonHelper->parse($this->subject, $this->getPath($options)); 123 | 124 | if (is_object($data)) { 125 | $data = get_object_vars($data); 126 | } 127 | 128 | if (!(is_array($data) || is_string($data))) { 129 | throw new JsonSizeException('Can\'t get size of scalar JSON value'); 130 | } 131 | 132 | if ($this->isPositive($options) ^ $expectedSize === count($data)) { 133 | throw JsonSizeException::create($expectedSize, count($data), $options); 134 | } 135 | 136 | return $this; 137 | } 138 | 139 | /** 140 | * Checks that given JSON at specific path have expected path. 141 | * 142 | * @param string $type 143 | * 144 | * @return $this 145 | */ 146 | public function hasType($type, array $options = []) 147 | { 148 | $data = $this->jsonHelper->parse($this->subject, $this->getPath($options)); 149 | 150 | if ('float' == $type) { 151 | $type = 'double'; 152 | } 153 | 154 | $actualType = gettype($data); 155 | if ($this->isPositive($options) ^ $actualType === $type) { 156 | throw JsonTypeException::create($type, $actualType, $options); 157 | } 158 | 159 | return $this; 160 | } 161 | 162 | /** 163 | * Checks that given JSON presents in some collection or property. 164 | * 165 | * @param string $json 166 | * 167 | * @return $this 168 | */ 169 | public function includes($json, array $options = []) 170 | { 171 | $actual = $this->scrub($this->subject, $options); 172 | $expected = $this->scrub($json, array_diff_key( 173 | // we should pass all options except `path` 174 | $options, [static::OPTION_PATH => null] 175 | )); 176 | 177 | if ( 178 | $this->isPositive($options) ^ $this->jsonHelper->isIncludes( 179 | $this->jsonHelper->parse($actual), $expected 180 | ) 181 | ) { 182 | throw JsonIncludesException::create($options); 183 | } 184 | 185 | return $this; 186 | } 187 | 188 | /** 189 | * Sets subject on which matching will be performed. 190 | * 191 | * @param string $subject 192 | * 193 | * @return $this 194 | */ 195 | public function setSubject($subject) 196 | { 197 | $this->subject = $subject; 198 | 199 | return $this; 200 | } 201 | 202 | /** 203 | * Negative matching. 204 | * 205 | * @param string $name 206 | * 207 | * @return $this 208 | */ 209 | public function __call($name, array $arguments = []) 210 | { 211 | if (0 !== strpos($name, 'not')) { 212 | throw new \RuntimeException(sprintf('Method "%s" not exists', $name)); 213 | } 214 | 215 | $matcher = lcfirst(substr($name, 3)); 216 | if (!method_exists($this, $matcher)) { 217 | throw new \RuntimeException(sprintf('Matcher "%s" not supported', $matcher)); 218 | } 219 | 220 | if (count($arguments) < 1) { 221 | throw new \RuntimeException('Matcher requires at least one argument'); 222 | } 223 | 224 | $options = array_pop($arguments); 225 | if (!is_array($options)) { 226 | array_push($arguments, $options); 227 | $options = []; 228 | } 229 | 230 | $options[self::OPTION_NEGATIVE] = true; 231 | array_push($arguments, $options); 232 | 233 | return !call_user_func_array([$this, $matcher], $arguments); 234 | } 235 | 236 | /** 237 | * Prepares JSON for matching. 238 | * 239 | * @param string $json 240 | * 241 | * @return string 242 | */ 243 | private function scrub($json, array $options = []) 244 | { 245 | return $this->jsonHelper->generateNormalizedJson( 246 | $this->jsonHelper->excludeKeys( 247 | $this->jsonHelper->parse($json, $this->getPath($options)), 248 | $this->getExcludedKeys($options) 249 | ) 250 | ); 251 | } 252 | 253 | /** 254 | * @return string|null 255 | */ 256 | private function getPath(array $options) 257 | { 258 | return $this->option($options, static::OPTION_PATH, null); 259 | } 260 | 261 | /** 262 | * @return array 263 | */ 264 | private function getExcludedKeys(array $options) 265 | { 266 | $excludedKeys = $this->option($options, static::OPTION_EXCLUDE_KEYS, []); 267 | $includedKeys = $this->option($options, static::OPTION_INCLUDE_KEYS, []); 268 | 269 | return array_diff(array_merge($this->excludeKeys, $excludedKeys), $includedKeys); 270 | } 271 | 272 | /** 273 | * @param string $optionName 274 | */ 275 | private function option(array $options, $optionName, $default = null) 276 | { 277 | return array_key_exists($optionName, $options) ? 278 | $options[$optionName] : $default 279 | ; 280 | } 281 | 282 | /** 283 | * @return bool 284 | */ 285 | private function isPositive(array $options) 286 | { 287 | return empty($options[self::OPTION_NEGATIVE]); 288 | } 289 | } 290 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Json Matcher 2 | ==================== 3 | 4 | [![Build Status](https://travis-ci.org/fesor/json_matcher.svg?branch=master)](https://travis-ci.org/fesor/json_matcher) 5 | [![Latest Stable Version](https://poser.pugx.org/fesor/json_matcher/v/stable.svg)](https://packagist.org/packages/fesor/json_matcher) 6 | [![Latest Unstable Version](https://poser.pugx.org/fesor/json_matcher/v/unstable.svg)](https://packagist.org/packages/fesor/json_matcher) 7 | [![License](https://poser.pugx.org/fesor/json_matcher/license.svg)](https://packagist.org/packages/fesor/json_matcher) 8 | [![Scrutinizer Code Quality](https://scrutinizer-ci.com/g/fesor/json_matcher/badges/quality-score.png?b=master)](https://scrutinizer-ci.com/g/fesor/json_matcher/?branch=master) 9 | [![Total Downloads](https://poser.pugx.org/fesor/json_matcher/downloads.svg)](https://packagist.org/packages/fesor/json_matcher) 10 | 11 | Assertion library for simplifying JSON data and structure verification in your tests. It's framework-agnostic, so you can use it with PhpUnit, PhpSpec, Peridot or whatever framework you use. 12 | 13 | ## Why another JSON assertion library? 14 | 15 | If you tried to test your JSON based REST APIs, then you probably faced a several issues: 16 | 17 | - You can't simply check is a response is equal to given string as there are things like server-generated IDs and timestamps. 18 | - Key ordering should be the same both for your API and for expected JSON. 19 | - Matching the whole responses breaks DRY for the tests 20 | 21 | All these issues can be solved with two simple things: JSON normalization and key exclusion on matching. This is what this library does. It provides you a way to verify data in given JSON in multiple steps instead of one big assertion. 22 | 23 | For example we are developing an friend list feature for our API for. What we want to check is only is given user presents in response, we don't want to check whole response, it could be done via json schema validation or on another test cases. 24 | 25 | ```php 26 | 27 | $alice = new User('Alice', 'Miller'); 28 | $john = new User('John', 'Smith'); 29 | $alice->addFriend($john); 30 | 31 | $json = JsonMatcher::create( 32 | json_encode($alice->toArrayIncludingFriends()), ['id', 'created_at'] 33 | ); 34 | 35 | ``` 36 | 37 | In above example we just created an `JsonMatcher` instance and specified excluded-by-default keys (`id` and `created_at`). Excluded keys will be removed from JSON and it's values will not interfere in equality assertion. You can also override this list of keys via matching `excluding` and `including` options. 38 | 39 | Then we can check is John presents in Alice's friend list at some specific position via json paths: 40 | ```php 41 | $json->equal(json_encode($john->toArray()), ['at' => 'friends/0']); 42 | ``` 43 | 44 | Or if we don't know specific position, we can just check is John just presents in our friendlist. 45 | ```php 46 | $json->includes(json_encode($john->toArray()), ['at' => 'friends']); 47 | ``` 48 | 49 | Or we can just verify is any John presents in Alice's friend list: 50 | ```php 51 | $json->includes('{"first_name": "John"}'), ['at' => 'friends']); 52 | ``` 53 | 54 | ## Getting started 55 | 56 | You can install this library via composer: 57 | ``` 58 | composer require fesor/json_matcher 59 | ``` 60 | 61 | Then you will need an `JsonMatcher` instance to be created. To do this, you can: 62 | 63 | - manually create instance with all dependencies and set subject 64 | - use named constructor `JsonMatcher::create` as static factory-method. It will handle all dependencies for you. 65 | - use JsonMatcherFactory. This is useful when you have some IoC container in your test framework (Behat for example). In this case you'll need to register this class as a service. 66 | 67 | Subject on which assertion will be preformed is setted up in matcher consturctor. If you want to reuse the same instance of matcher for every assertions, you can just change subject via `setSubject` method. 68 | 69 | Example: 70 | ```php 71 | $jsonResponse = JsonMatcher::create($response->getContent()); 72 | 73 | // or you can use factory instead 74 | $jsonResponse = $matcherFactory->create($response->getContent()); 75 | 76 | // and there you go, for example you may use something like this 77 | // for your gherkin steps implementations 78 | $jsonResponse 79 | ->hasSize(1, ['at' => 'friends']) // checks that list of friends was incremented 80 | ->includes($friend, ['at' => 'friends']) // checks that correct record contained in collection 81 | ; 82 | ``` 83 | 84 | You can provide list of excluded-by-default keys as second argument in constructors: 85 | ```php 86 | $matcher = JsonMatcher::create($subject, ['id', 'created_at']); 87 | ``` 88 | 89 | Please note, that `id` key will be ignored by default. 90 | 91 | ## Matchers 92 | 93 | All matchers are supports fluent interface, negative matching and some options. See detailed description for more information about what options each matcher has. 94 | 95 | ### equal 96 | This is most commonly used matcher. You take two json strings and compare them. Except that before compassion this matcher will normalize structure of both JSON strings, reorder keys, exclude some of them (this is configurable) and then will simply assert that both strings are equal. You can specify list of excluded keys with `excluding` options: 97 | ```php 98 | $actualJson = '["id": 1, "json": "spec"]'; 99 | $expectedJson = '["json": "spec"]'; 100 | $matcher 101 | ->setSubject($actualJson) 102 | ->equal($expectedJson, ['excluding' => ['id']]) 103 | ; 104 | ``` 105 | 106 | If you have some keys, which contains some time dependent value of some server-generated IDs it is more convenient to specify list of excluded-by-default keys when you construct matcher object: 107 | ```php 108 | $matcher = JsonMatcher::create($subject, ['id', 'created_at', 'updated_at']); 109 | ``` 110 | 111 | If you want the values for these keys to be taken into account during the matching, you can specify list of included keys with `including` options 112 | ```php 113 | $matcher = JsonMatcher::create($response->getContent(), ['id', 'created_at', 'updated_at']); 114 | $jsonResponseSubject->equal($expectedJson, ['including' => ['id']]); 115 | ``` 116 | 117 | Also you can specify json path on which matching should be done via `at` options. We will back to this later since all matchers supports this option. 118 | 119 | ### includes 120 | This matcher works a little different from `equal` matcher. What it does is recursively scan subject JSON and tries to find any inclusions of JSON subset. This is useful for cases when you checking that some record exists in collection and you do not know or don't want to know specific path to it. 121 | 122 | ```php 123 | $json = <<setSubject($json) 136 | // check for value inclusion 137 | ->includes('"Foo"') 138 | // checks is json subset presents in any item of collection 139 | ->includes('{"name": "Bar"}', ['at' => 'collection']) 140 | // checks is json presents in collection 141 | ->includes('{"name": "Bar", "value": "FooBar"}', ['at' => 'collection']) 142 | ; 143 | ``` 144 | 145 | Since this matcher works the same way as `equal` matcher, it accepts same options. 146 | 147 | ### hasPath 148 | This matcher checks if given JSON have specific path ot not. 149 | 150 | ```php 151 | $json = <<setSubject($json) 162 | ->hasPath('collection/1') 163 | ; 164 | ``` 165 | 166 | ### hasSize 167 | This matcher checks is collection in given JSON contains specific amount of entities. 168 | 169 | ```php 170 | $json = <<setSubject($json) 181 | ->hasSize(2, ['at' => 'collection']) 182 | ; 183 | ``` 184 | 185 | ### hasType 186 | ```php 187 | $json = <<setSubject($json) 200 | ->hasType('array', ['at' => 'collection']) 201 | ->hasType('object', ['at' => 'collection/0']) 202 | ->hasType('string', ['at' => 'collection/1']) 203 | ->hasType('integer', ['at' => 'collection/2']) 204 | ->hasType('float', ['at' => 'collection/3']) 205 | ; 206 | ``` 207 | 208 | ### Negative matching 209 | To invert expectations just call matcher methods with `not` prefix: 210 | ```php 211 | $matcher 212 | ->setSubject($json) 213 | ->notEqual($expected) 214 | ->notIncludes($part) 215 | ; 216 | ``` 217 | 218 | ### Json Path 219 | Also all methods have option, which specifies path which should be performed matching. For example: 220 | 221 | ```php 222 | $actual = <<equal($expected, ['at' => 'collection/0']) 232 | ; 233 | ``` 234 | ## Contribution 235 | Please welcome to contribute! 236 | 237 | -------------------------------------------------------------------------------- /spec/JsonMatcherSpec.php: -------------------------------------------------------------------------------- 1 | beConstructedWith(new JsonHelper(), ['id']); 20 | } 21 | 22 | // 23 | public function it_supports_negative_matching() 24 | { 25 | $json = '{"json": "spec"}'; 26 | $this->setSubject($json)->shouldThrow(self::$equalityException)->duringNotEqual($json); 27 | } 28 | 29 | public function it_checks_is_matcher_supported() 30 | { 31 | $this->shouldThrow(new \RuntimeException('Matcher "match" not supported'))->duringNotMatch(); 32 | } 33 | 34 | public function it_checks_is_method_exists() 35 | { 36 | $this->shouldThrow(new \RuntimeException('Method "match" not exists'))->duringMatch(); 37 | } 38 | 39 | public function it_validates_argument_count() 40 | { 41 | $this->shouldThrow(new \RuntimeException('Matcher requires at least one argument'))->duringNotEqual(); 42 | } 43 | 44 | // 45 | 46 | // 47 | public function it_matches_identical_JSON() 48 | { 49 | $this->setSubject(('{"json":"spec"}'))->shouldNotThrow()->duringEqual('{"json":"spec"}'); 50 | } 51 | 52 | public function it_matches_not_identical_JSON_for_nagetive_matching() 53 | { 54 | $this->setSubject(('{"json":"spec"}'))->shouldNotThrow()->duringNotEqual('{"spec":"json"}'); 55 | } 56 | 57 | public function it_matches_differently_formatted_JSON() 58 | { 59 | $this->setSubject(('{"json": "spec"}'))->shouldNotThrow()->duringEqual('{"json":"spec"}'); 60 | } 61 | 62 | public function it_matches_out_of_order_hashes() 63 | { 64 | $this->setSubject(('{"laser":"lemon","json":"spec"}'))->shouldNotThrow()->duringEqual('{"json":"spec","laser":"lemon"}'); 65 | } 66 | 67 | public function it_does_not_match_out_of_order_arrays() 68 | { 69 | $this->setSubject(('["json","spec"]'))->shouldThrow(self::$equalityException)->duringEqual('["spec", "json"]'); 70 | } 71 | 72 | public function it_does_match_out_of_order_arrays_on_negative() 73 | { 74 | $this->setSubject(('["json","spec"]'))->shouldNotThrow()->duringNotEqual('["spec", "json"]'); 75 | } 76 | 77 | public function it_matches_valid_JSON_values_yet_invalid_JSON_documents() 78 | { 79 | $this->setSubject(('"json_spec"'))->shouldNotThrow()->duringEqual('"json_spec"'); 80 | } 81 | 82 | public function it_matches_at_a_path() 83 | { 84 | $this->setSubject(('{"json":["spec"]}'))->shouldNotThrow()->duringEqual('"spec"', ['at' => 'json/0']); 85 | } 86 | 87 | public function it_ignores_excluded_by_default_hash_keys() 88 | { 89 | $this->setSubject(('{"id": 1, "json":["spec"]}'))->shouldNotThrow()->duringEqual('{"id": 2, "json":["spec"]}'); 90 | } 91 | 92 | public function it_not_ignores_excluded_by_default_hash_keys_if_it_setted_as_included() 93 | { 94 | $this->setSubject(('{"id": 1, "json":["spec"]}')) 95 | ->shouldThrow(self::$equalityException) 96 | ->duringEqual('{"id": 2, "json":["spec"]}', [ 97 | 'including' => ['id'], 98 | ]) 99 | ; 100 | } 101 | 102 | public function it_ignores_custom_excluded_hash_keys() 103 | { 104 | $this->setSubject(('{"json":"spec","ignore":"please"}')) 105 | ->shouldNotThrow() 106 | ->duringEqual('{"json":"spec"}', [ 107 | 'excluding' => ['ignore'], 108 | ]) 109 | ; 110 | } 111 | 112 | public function it_ignores_nested_excluded_hash_keys() 113 | { 114 | $this->setSubject(('{"json":"spec","please":{"ignore":"this"}}')) 115 | ->shouldNotThrow() 116 | ->duringEqual('{"json":"spec","please":{}}', [ 117 | 'excluding' => ['ignore'], 118 | ]) 119 | ; 120 | } 121 | 122 | public function it_ignores_hash_keys_when_included_in_the_expected_value() 123 | { 124 | $this->setSubject(('{"json":"spec","ignore":"please"}')) 125 | ->shouldNotThrow() 126 | ->duringEqual('{"json":"spec","ignore":"this"}', [ 127 | 'excluding' => ['ignore'], 128 | ]) 129 | ; 130 | } 131 | 132 | public function it_matches_different_looking_JSON_equivalent_values() 133 | { 134 | $this->setSubject(('{"ten":10.0}'))->shouldNotThrow()->duringEqual('{"ten":1e+1}'); 135 | } 136 | 137 | public function it_excludes_multiple_keys() 138 | { 139 | $this->setSubject(('{"id":1,"json":"spec"}'))->shouldNotThrow()->duringEqual('{"id":2,"json":"different"}', [ 140 | 'excluding' => ['id', 'json'], 141 | ]); 142 | } 143 | 144 | // 145 | 146 | // 147 | public function it_matches_hash_keys() 148 | { 149 | $this->setSubject(('{"one":{"two":{"three":4}}}'))->shouldNotThrow()->duringHasPath('one/two/three'); 150 | } 151 | 152 | public function it_does_not_match_values() 153 | { 154 | $this->setSubject(('{"one":{"two":{"three":4}}}'))->shouldThrow(self::$pathMatchException)->duringHasPath('one/two/three/4'); 155 | } 156 | 157 | public function it_matches_array_indexes() 158 | { 159 | $this->setSubject(('[1,[1,2,[1,2,3,4]]]'))->shouldNotThrow()->duringHasPath('1/2/3'); 160 | } 161 | 162 | public function it_respects_null_array_values() 163 | { 164 | $this->setSubject(('[null,[null,null,[null,null,null,null]]]'))->shouldNotThrow()->duringHasPath('1/2/3'); 165 | } 166 | 167 | public function it_matches_hash_keys_and_array_indexes() 168 | { 169 | $this->setSubject(('{"one":[1,2,{"three":4}]}'))->shouldNotThrow()->duringHasPath('one/2/three'); 170 | } 171 | 172 | public function it_matches_hash_keys_with_given_base_path() 173 | { 174 | $this->setSubject(('{"one":{"two":{"three":4}}}'))->shouldNotThrow()->duringHasPath('two/three', ['at' => 'one']); 175 | } 176 | 177 | public function it_matches_that_json_path_not_exists() 178 | { 179 | $this->setSubject('{}')->shouldNotThrow()->duringNotHasPath('not_existing'); 180 | } 181 | 182 | // 183 | 184 | // 185 | public function it_counts_array_entries() 186 | { 187 | $this->setSubject(('[1,2,3]'))->shouldNotThrow()->duringHasSize(3); 188 | } 189 | 190 | public function it_counts_null_array_entries() 191 | { 192 | $this->setSubject(('[1,null,3]'))->shouldNotThrow()->duringHasSize(3); 193 | } 194 | 195 | public function it_counts_hash_key_value_pairs() 196 | { 197 | $this->setSubject(('{"one":1,"two":2,"three":3}'))->shouldNotThrow()->duringHasSize(3); 198 | } 199 | 200 | public function it_counts_null_hash_values() 201 | { 202 | $this->setSubject(('{"one":1,"two":null,"three":3}'))->shouldNotThrow()->duringHasSize(3); 203 | } 204 | 205 | public function it_matches_size_at_a_path() 206 | { 207 | $this->setSubject(('{"one":[1,2,3]}'))->shouldNotThrow()->duringHasSize(3, ['at' => 'one']); 208 | } 209 | 210 | public function it_fails_on_wrong_ammount_of_items() 211 | { 212 | $this->setSubject(('[1,null]'))->shouldThrow()->duringHasSize(3); 213 | } 214 | 215 | public function it_matches_size_in_nagative_scenarios() 216 | { 217 | $this->setSubject(('[1,null]'))->shouldNotThrow()->duringNotHasSize(3); 218 | } 219 | 220 | public function it_cant_match_size_of_scalars() 221 | { 222 | $this->setSubject(('{"one":[1,2,3]}')) 223 | ->shouldThrow(self::$jsonSizeException) 224 | ->duringHasSize(3, ['at' => 'one/0']) 225 | ; 226 | } 227 | 228 | // 229 | 230 | // 231 | public function it_matches_objects() 232 | { 233 | $this->setSubject(('{}'))->shouldNotThrow()->duringHasType('object'); 234 | } 235 | 236 | public function it_matches_arrays() 237 | { 238 | $this->setSubject(('[]'))->shouldNotThrow()->duringHasType('array'); 239 | } 240 | 241 | public function it_matches_type_at_a_path() 242 | { 243 | $this->setSubject(('{"root":[]}')) 244 | ->shouldNotThrow() 245 | ->duringHasType('array', [ 246 | 'at' => 'root', 247 | ]) 248 | ; 249 | } 250 | 251 | public function it_matches_strings() 252 | { 253 | $this->setSubject(('["json_spec"]'))->shouldNotThrow()->duringHasType('string', ['at' => '0']); 254 | } 255 | 256 | public function it_matches_a_valid_JSON_value_yet_invalid_JSON_document() 257 | { 258 | $this->setSubject(('"json_spec"'))->shouldNotThrow()->duringHasType('string'); 259 | } 260 | 261 | public function it_matches_empty_strings() 262 | { 263 | $this->setSubject(('""'))->shouldNotThrow()->duringHasType('string'); 264 | } 265 | 266 | public function it_matches_integers() 267 | { 268 | $this->setSubject(('10'))->shouldNotThrow()->duringHasType('integer'); 269 | } 270 | 271 | public function it_matches_floats() 272 | { 273 | $this->setSubject(('10.0'))->shouldNotThrow()->duringHasType('float'); 274 | $this->setSubject(('1e+1'))->shouldNotThrow()->duringHasType('float'); 275 | } 276 | 277 | public function it_matches_booleans() 278 | { 279 | $this->setSubject(('true'))->shouldNotThrow()->duringHasType('boolean'); 280 | $this->setSubject(('false'))->shouldNotThrow()->duringHasType('boolean'); 281 | } 282 | 283 | // 284 | 285 | // 286 | public function it_matches_included_array_elements() 287 | { 288 | $json = '["one",1,1.0,true,false,null]'; 289 | $this->setSubject(($json))->shouldNotThrow()->duringIncludes('"one"'); 290 | $this->setSubject(($json))->shouldNotThrow()->duringIncludes('1'); 291 | $this->setSubject(($json))->shouldNotThrow()->duringIncludes('1.0'); 292 | $this->setSubject(($json))->shouldNotThrow()->duringIncludes('true'); 293 | $this->setSubject(($json))->shouldNotThrow()->duringIncludes('false'); 294 | $this->setSubject(($json))->shouldNotThrow()->duringIncludes('null'); 295 | } 296 | 297 | public function it_matches_an_array_included_in_an_array() 298 | { 299 | $json = '[[1,2,3],[4,5,6]]'; 300 | $this->setSubject(($json))->shouldNotThrow()->duringIncludes('[1, 2, 3]'); 301 | $this->setSubject(($json))->shouldNotThrow()->duringIncludes('[4, 5, 6]'); 302 | } 303 | 304 | public function it_matches_a_hash_included_in_an_array() 305 | { 306 | $json = '[{"one":1},{"two":2}]'; 307 | $this->setSubject(($json))->shouldNotThrow()->duringIncludes('{"one":1}'); 308 | $this->setSubject(($json))->shouldNotThrow()->duringIncludes('{"two":2}'); 309 | } 310 | 311 | public function it_matches_included_hash_values() 312 | { 313 | $json = '{"string":"one","integer":1,"float":1.0,"true":true,"false":false,"null":null}'; 314 | $this->setSubject(($json))->shouldNotThrow()->duringIncludes('"one"'); 315 | $this->setSubject(($json))->shouldNotThrow()->duringIncludes('1'); 316 | $this->setSubject(($json))->shouldNotThrow()->duringIncludes('1.0'); 317 | $this->setSubject(($json))->shouldNotThrow()->duringIncludes('true'); 318 | $this->setSubject(($json))->shouldNotThrow()->duringIncludes('false'); 319 | $this->setSubject(($json))->shouldNotThrow()->duringIncludes('null'); 320 | } 321 | 322 | public function it_matches_a_hash_included_in_a_hash() 323 | { 324 | $json = '{"one":{"two":3},"four":{"five":6}}'; 325 | $this->setSubject(($json))->shouldNotThrow()->duringIncludes('{"two":3}'); 326 | $this->setSubject(($json))->shouldNotThrow()->duringIncludes('{"five":6}'); 327 | } 328 | 329 | public function it_matches_an_array_included_in_a_hash() 330 | { 331 | $json = '{"one":[2,3],"four":[5,6]}'; 332 | $this->setSubject(($json))->shouldNotThrow()->duringIncludes('[2,3]'); 333 | $this->setSubject(($json))->shouldNotThrow()->duringIncludes('[5,6]'); 334 | } 335 | 336 | public function it_matches_a_substring() 337 | { 338 | $json = '"json"'; 339 | $this->setSubject(($json))->shouldNotThrow()->duringIncludes('"js"'); 340 | $this->setSubject(($json))->shouldNotThrow()->duringIncludes('"json"'); 341 | } 342 | 343 | public function it_matches_t_a_path() 344 | { 345 | $json = '{"one":{"two":[3,4]}}'; 346 | $this->setSubject(($json))->shouldNotThrow()->duringIncludes('[3,4]', ['at' => 'one']); 347 | } 348 | 349 | public function it_ignores_excluded_keys() 350 | { 351 | $json = '[{"id":1,"two":3}]'; 352 | $this->setSubject(($json))->shouldNotThrow()->duringIncludes('{"two":3}'); 353 | } 354 | 355 | public function it_matches_an_subset_included_in_a_hash() 356 | { 357 | $json = '{"id": 1, "name": "Foo"}'; 358 | $this->setSubject($json)->shouldNotThrow()->duringIncludes('{"name":"Foo"}'); 359 | } 360 | 361 | public function it_matches_an_subset_included_in_a_collection_of_hashes() 362 | { 363 | $json = '[{"id": 1, "name": "Foo"}, {"id": 2, "name": "Bar"}]'; 364 | $this->setSubject($json)->shouldNotThrow()->duringIncludes('{"name":"Bar"}'); 365 | } 366 | 367 | public function it_should_throw_exception_if_it_cant_find_subset_in_hash() 368 | { 369 | $json = '{"id": 1, "name": "Foo"}'; 370 | $this->setSubject($json)->shouldThrow()->duringIncludes('{"name":"Bar"}'); 371 | } 372 | 373 | // 374 | } 375 | -------------------------------------------------------------------------------- /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": "60b01f3531131c8aaeee10a351b2579d", 8 | "packages": [], 9 | "packages-dev": [ 10 | { 11 | "name": "composer/semver", 12 | "version": "1.5.1", 13 | "source": { 14 | "type": "git", 15 | "url": "https://github.com/composer/semver.git", 16 | "reference": "c6bea70230ef4dd483e6bbcab6005f682ed3a8de" 17 | }, 18 | "dist": { 19 | "type": "zip", 20 | "url": "https://api.github.com/repos/composer/semver/zipball/c6bea70230ef4dd483e6bbcab6005f682ed3a8de", 21 | "reference": "c6bea70230ef4dd483e6bbcab6005f682ed3a8de", 22 | "shasum": "" 23 | }, 24 | "require": { 25 | "php": "^5.3.2 || ^7.0" 26 | }, 27 | "require-dev": { 28 | "phpunit/phpunit": "^4.5 || ^5.0.5" 29 | }, 30 | "type": "library", 31 | "extra": { 32 | "branch-alias": { 33 | "dev-master": "1.x-dev" 34 | } 35 | }, 36 | "autoload": { 37 | "psr-4": { 38 | "Composer\\Semver\\": "src" 39 | } 40 | }, 41 | "notification-url": "https://packagist.org/downloads/", 42 | "license": [ 43 | "MIT" 44 | ], 45 | "authors": [ 46 | { 47 | "name": "Nils Adermann", 48 | "email": "naderman@naderman.de", 49 | "homepage": "http://www.naderman.de" 50 | }, 51 | { 52 | "name": "Jordi Boggiano", 53 | "email": "j.boggiano@seld.be", 54 | "homepage": "http://seld.be" 55 | }, 56 | { 57 | "name": "Rob Bast", 58 | "email": "rob.bast@gmail.com", 59 | "homepage": "http://robbast.nl" 60 | } 61 | ], 62 | "description": "Semver library that offers utilities, version constraint parsing and validation.", 63 | "keywords": [ 64 | "semantic", 65 | "semver", 66 | "validation", 67 | "versioning" 68 | ], 69 | "time": "2020-01-13T12:06:48+00:00" 70 | }, 71 | { 72 | "name": "composer/xdebug-handler", 73 | "version": "1.4.1", 74 | "source": { 75 | "type": "git", 76 | "url": "https://github.com/composer/xdebug-handler.git", 77 | "reference": "1ab9842d69e64fb3a01be6b656501032d1b78cb7" 78 | }, 79 | "dist": { 80 | "type": "zip", 81 | "url": "https://api.github.com/repos/composer/xdebug-handler/zipball/1ab9842d69e64fb3a01be6b656501032d1b78cb7", 82 | "reference": "1ab9842d69e64fb3a01be6b656501032d1b78cb7", 83 | "shasum": "" 84 | }, 85 | "require": { 86 | "php": "^5.3.2 || ^7.0 || ^8.0", 87 | "psr/log": "^1.0" 88 | }, 89 | "require-dev": { 90 | "phpunit/phpunit": "^4.8.35 || ^5.7 || 6.5 - 8" 91 | }, 92 | "type": "library", 93 | "autoload": { 94 | "psr-4": { 95 | "Composer\\XdebugHandler\\": "src" 96 | } 97 | }, 98 | "notification-url": "https://packagist.org/downloads/", 99 | "license": [ 100 | "MIT" 101 | ], 102 | "authors": [ 103 | { 104 | "name": "John Stevenson", 105 | "email": "john-stevenson@blueyonder.co.uk" 106 | } 107 | ], 108 | "description": "Restarts a process without Xdebug.", 109 | "keywords": [ 110 | "Xdebug", 111 | "performance" 112 | ], 113 | "funding": [ 114 | { 115 | "url": "https://packagist.com", 116 | "type": "custom" 117 | } 118 | ], 119 | "time": "2020-03-01T12:26:26+00:00" 120 | }, 121 | { 122 | "name": "doctrine/annotations", 123 | "version": "1.10.2", 124 | "source": { 125 | "type": "git", 126 | "url": "https://github.com/doctrine/annotations.git", 127 | "reference": "b9d758e831c70751155c698c2f7df4665314a1cb" 128 | }, 129 | "dist": { 130 | "type": "zip", 131 | "url": "https://api.github.com/repos/doctrine/annotations/zipball/b9d758e831c70751155c698c2f7df4665314a1cb", 132 | "reference": "b9d758e831c70751155c698c2f7df4665314a1cb", 133 | "shasum": "" 134 | }, 135 | "require": { 136 | "doctrine/lexer": "1.*", 137 | "ext-tokenizer": "*", 138 | "php": "^7.1" 139 | }, 140 | "require-dev": { 141 | "doctrine/cache": "1.*", 142 | "phpunit/phpunit": "^7.5" 143 | }, 144 | "type": "library", 145 | "extra": { 146 | "branch-alias": { 147 | "dev-master": "1.9.x-dev" 148 | } 149 | }, 150 | "autoload": { 151 | "psr-4": { 152 | "Doctrine\\Common\\Annotations\\": "lib/Doctrine/Common/Annotations" 153 | } 154 | }, 155 | "notification-url": "https://packagist.org/downloads/", 156 | "license": [ 157 | "MIT" 158 | ], 159 | "authors": [ 160 | { 161 | "name": "Guilherme Blanco", 162 | "email": "guilhermeblanco@gmail.com" 163 | }, 164 | { 165 | "name": "Roman Borschel", 166 | "email": "roman@code-factory.org" 167 | }, 168 | { 169 | "name": "Benjamin Eberlei", 170 | "email": "kontakt@beberlei.de" 171 | }, 172 | { 173 | "name": "Jonathan Wage", 174 | "email": "jonwage@gmail.com" 175 | }, 176 | { 177 | "name": "Johannes Schmitt", 178 | "email": "schmittjoh@gmail.com" 179 | } 180 | ], 181 | "description": "Docblock Annotations Parser", 182 | "homepage": "http://www.doctrine-project.org", 183 | "keywords": [ 184 | "annotations", 185 | "docblock", 186 | "parser" 187 | ], 188 | "time": "2020-04-20T09:18:32+00:00" 189 | }, 190 | { 191 | "name": "doctrine/instantiator", 192 | "version": "1.3.0", 193 | "source": { 194 | "type": "git", 195 | "url": "https://github.com/doctrine/instantiator.git", 196 | "reference": "ae466f726242e637cebdd526a7d991b9433bacf1" 197 | }, 198 | "dist": { 199 | "type": "zip", 200 | "url": "https://api.github.com/repos/doctrine/instantiator/zipball/ae466f726242e637cebdd526a7d991b9433bacf1", 201 | "reference": "ae466f726242e637cebdd526a7d991b9433bacf1", 202 | "shasum": "" 203 | }, 204 | "require": { 205 | "php": "^7.1" 206 | }, 207 | "require-dev": { 208 | "doctrine/coding-standard": "^6.0", 209 | "ext-pdo": "*", 210 | "ext-phar": "*", 211 | "phpbench/phpbench": "^0.13", 212 | "phpstan/phpstan-phpunit": "^0.11", 213 | "phpstan/phpstan-shim": "^0.11", 214 | "phpunit/phpunit": "^7.0" 215 | }, 216 | "type": "library", 217 | "extra": { 218 | "branch-alias": { 219 | "dev-master": "1.2.x-dev" 220 | } 221 | }, 222 | "autoload": { 223 | "psr-4": { 224 | "Doctrine\\Instantiator\\": "src/Doctrine/Instantiator/" 225 | } 226 | }, 227 | "notification-url": "https://packagist.org/downloads/", 228 | "license": [ 229 | "MIT" 230 | ], 231 | "authors": [ 232 | { 233 | "name": "Marco Pivetta", 234 | "email": "ocramius@gmail.com", 235 | "homepage": "http://ocramius.github.com/" 236 | } 237 | ], 238 | "description": "A small, lightweight utility to instantiate objects in PHP without invoking their constructors", 239 | "homepage": "https://www.doctrine-project.org/projects/instantiator.html", 240 | "keywords": [ 241 | "constructor", 242 | "instantiate" 243 | ], 244 | "time": "2019-10-21T16:45:58+00:00" 245 | }, 246 | { 247 | "name": "doctrine/lexer", 248 | "version": "1.2.0", 249 | "source": { 250 | "type": "git", 251 | "url": "https://github.com/doctrine/lexer.git", 252 | "reference": "5242d66dbeb21a30dd8a3e66bf7a73b66e05e1f6" 253 | }, 254 | "dist": { 255 | "type": "zip", 256 | "url": "https://api.github.com/repos/doctrine/lexer/zipball/5242d66dbeb21a30dd8a3e66bf7a73b66e05e1f6", 257 | "reference": "5242d66dbeb21a30dd8a3e66bf7a73b66e05e1f6", 258 | "shasum": "" 259 | }, 260 | "require": { 261 | "php": "^7.2" 262 | }, 263 | "require-dev": { 264 | "doctrine/coding-standard": "^6.0", 265 | "phpstan/phpstan": "^0.11.8", 266 | "phpunit/phpunit": "^8.2" 267 | }, 268 | "type": "library", 269 | "extra": { 270 | "branch-alias": { 271 | "dev-master": "1.2.x-dev" 272 | } 273 | }, 274 | "autoload": { 275 | "psr-4": { 276 | "Doctrine\\Common\\Lexer\\": "lib/Doctrine/Common/Lexer" 277 | } 278 | }, 279 | "notification-url": "https://packagist.org/downloads/", 280 | "license": [ 281 | "MIT" 282 | ], 283 | "authors": [ 284 | { 285 | "name": "Guilherme Blanco", 286 | "email": "guilhermeblanco@gmail.com" 287 | }, 288 | { 289 | "name": "Roman Borschel", 290 | "email": "roman@code-factory.org" 291 | }, 292 | { 293 | "name": "Johannes Schmitt", 294 | "email": "schmittjoh@gmail.com" 295 | } 296 | ], 297 | "description": "PHP Doctrine Lexer parser library that can be used in Top-Down, Recursive Descent Parsers.", 298 | "homepage": "https://www.doctrine-project.org/projects/lexer.html", 299 | "keywords": [ 300 | "annotations", 301 | "docblock", 302 | "lexer", 303 | "parser", 304 | "php" 305 | ], 306 | "time": "2019-10-30T14:39:59+00:00" 307 | }, 308 | { 309 | "name": "friends-of-phpspec/phpspec-code-coverage", 310 | "version": "v4.3.2", 311 | "source": { 312 | "type": "git", 313 | "url": "https://github.com/friends-of-phpspec/phpspec-code-coverage.git", 314 | "reference": "9a54302573094cc1b3bdca3cc78c58582130b254" 315 | }, 316 | "dist": { 317 | "type": "zip", 318 | "url": "https://api.github.com/repos/friends-of-phpspec/phpspec-code-coverage/zipball/9a54302573094cc1b3bdca3cc78c58582130b254", 319 | "reference": "9a54302573094cc1b3bdca3cc78c58582130b254", 320 | "shasum": "" 321 | }, 322 | "require": { 323 | "php": "^7.1", 324 | "phpspec/phpspec": "^4.2 || ^5.0 || ^6.0", 325 | "phpunit/php-code-coverage": "^5.0 || ^6.0 || ^7.0" 326 | }, 327 | "require-dev": { 328 | "drupol/php-conventions": "^1", 329 | "scrutinizer/ocular": "^1" 330 | }, 331 | "suggest": { 332 | "ext-pcov": "Install PCov extension to generate code coverage.", 333 | "ext-xdebug": "Install Xdebug to generate phpspec code coverage." 334 | }, 335 | "type": "library", 336 | "extra": { 337 | "branch-alias": { 338 | "dev-master": "4.x-dev" 339 | } 340 | }, 341 | "autoload": { 342 | "psr-4": { 343 | "FriendsOfPhpSpec\\PhpSpec\\CodeCoverage\\": "src/" 344 | }, 345 | "files": [ 346 | "src/bootstrap.php" 347 | ] 348 | }, 349 | "notification-url": "https://packagist.org/downloads/", 350 | "license": [ 351 | "MIT" 352 | ], 353 | "authors": [ 354 | { 355 | "name": "ek9", 356 | "email": "dev@ek9.co", 357 | "homepage": "https://ek9.co" 358 | }, 359 | { 360 | "name": "Henrik Bjornskov" 361 | }, 362 | { 363 | "name": "Stéphane Hulard", 364 | "email": "s.hulard@chstudio.fr", 365 | "homepage": "https://chstudio.fr" 366 | }, 367 | { 368 | "name": "Pol Dellaiera", 369 | "email": "pol.dellaiera@protonmail.com", 370 | "homepage": "https://not-a-number.io/" 371 | }, 372 | { 373 | "name": "Jay Linski", 374 | "homepage": "https://twitter.com/jay_linski" 375 | } 376 | ], 377 | "description": "Generate Code Coverage reports for PhpSpec tests", 378 | "homepage": "https://github.com/friends-of-phpspec/phpspec-code-coverage", 379 | "keywords": [ 380 | "code-coverage", 381 | "coverage", 382 | "phpspec", 383 | "report", 384 | "spec", 385 | "test", 386 | "tests" 387 | ], 388 | "time": "2019-11-12T10:27:45+00:00" 389 | }, 390 | { 391 | "name": "friendsofphp/php-cs-fixer", 392 | "version": "v2.16.3", 393 | "source": { 394 | "type": "git", 395 | "url": "https://github.com/FriendsOfPHP/PHP-CS-Fixer.git", 396 | "reference": "83baf823a33a1cbd5416c8626935cf3f843c10b0" 397 | }, 398 | "dist": { 399 | "type": "zip", 400 | "url": "https://api.github.com/repos/FriendsOfPHP/PHP-CS-Fixer/zipball/83baf823a33a1cbd5416c8626935cf3f843c10b0", 401 | "reference": "83baf823a33a1cbd5416c8626935cf3f843c10b0", 402 | "shasum": "" 403 | }, 404 | "require": { 405 | "composer/semver": "^1.4", 406 | "composer/xdebug-handler": "^1.2", 407 | "doctrine/annotations": "^1.2", 408 | "ext-json": "*", 409 | "ext-tokenizer": "*", 410 | "php": "^5.6 || ^7.0", 411 | "php-cs-fixer/diff": "^1.3", 412 | "symfony/console": "^3.4.17 || ^4.1.6 || ^5.0", 413 | "symfony/event-dispatcher": "^3.0 || ^4.0 || ^5.0", 414 | "symfony/filesystem": "^3.0 || ^4.0 || ^5.0", 415 | "symfony/finder": "^3.0 || ^4.0 || ^5.0", 416 | "symfony/options-resolver": "^3.0 || ^4.0 || ^5.0", 417 | "symfony/polyfill-php70": "^1.0", 418 | "symfony/polyfill-php72": "^1.4", 419 | "symfony/process": "^3.0 || ^4.0 || ^5.0", 420 | "symfony/stopwatch": "^3.0 || ^4.0 || ^5.0" 421 | }, 422 | "require-dev": { 423 | "johnkary/phpunit-speedtrap": "^1.1 || ^2.0 || ^3.0", 424 | "justinrainbow/json-schema": "^5.0", 425 | "keradus/cli-executor": "^1.2", 426 | "mikey179/vfsstream": "^1.6", 427 | "php-coveralls/php-coveralls": "^2.1", 428 | "php-cs-fixer/accessible-object": "^1.0", 429 | "php-cs-fixer/phpunit-constraint-isidenticalstring": "^1.1", 430 | "php-cs-fixer/phpunit-constraint-xmlmatchesxsd": "^1.1", 431 | "phpunit/phpunit": "^5.7.27 || ^6.5.14 || ^7.1", 432 | "phpunitgoodpractices/traits": "^1.8", 433 | "symfony/phpunit-bridge": "^4.3 || ^5.0", 434 | "symfony/yaml": "^3.0 || ^4.0 || ^5.0" 435 | }, 436 | "suggest": { 437 | "ext-dom": "For handling output formats in XML", 438 | "ext-mbstring": "For handling non-UTF8 characters in cache signature.", 439 | "php-cs-fixer/phpunit-constraint-isidenticalstring": "For IsIdenticalString constraint.", 440 | "php-cs-fixer/phpunit-constraint-xmlmatchesxsd": "For XmlMatchesXsd constraint.", 441 | "symfony/polyfill-mbstring": "When enabling `ext-mbstring` is not possible." 442 | }, 443 | "bin": [ 444 | "php-cs-fixer" 445 | ], 446 | "type": "application", 447 | "autoload": { 448 | "psr-4": { 449 | "PhpCsFixer\\": "src/" 450 | }, 451 | "classmap": [ 452 | "tests/Test/AbstractFixerTestCase.php", 453 | "tests/Test/AbstractIntegrationCaseFactory.php", 454 | "tests/Test/AbstractIntegrationTestCase.php", 455 | "tests/Test/Assert/AssertTokensTrait.php", 456 | "tests/Test/IntegrationCase.php", 457 | "tests/Test/IntegrationCaseFactory.php", 458 | "tests/Test/IntegrationCaseFactoryInterface.php", 459 | "tests/Test/InternalIntegrationCaseFactory.php", 460 | "tests/Test/IsIdenticalConstraint.php", 461 | "tests/TestCase.php" 462 | ] 463 | }, 464 | "notification-url": "https://packagist.org/downloads/", 465 | "license": [ 466 | "MIT" 467 | ], 468 | "authors": [ 469 | { 470 | "name": "Fabien Potencier", 471 | "email": "fabien@symfony.com" 472 | }, 473 | { 474 | "name": "Dariusz Rumiński", 475 | "email": "dariusz.ruminski@gmail.com" 476 | } 477 | ], 478 | "description": "A tool to automatically fix PHP code style", 479 | "funding": [ 480 | { 481 | "url": "https://github.com/keradus", 482 | "type": "github" 483 | } 484 | ], 485 | "time": "2020-04-15T18:51:10+00:00" 486 | }, 487 | { 488 | "name": "paragonie/random_compat", 489 | "version": "v9.99.99", 490 | "source": { 491 | "type": "git", 492 | "url": "https://github.com/paragonie/random_compat.git", 493 | "reference": "84b4dfb120c6f9b4ff7b3685f9b8f1aa365a0c95" 494 | }, 495 | "dist": { 496 | "type": "zip", 497 | "url": "https://api.github.com/repos/paragonie/random_compat/zipball/84b4dfb120c6f9b4ff7b3685f9b8f1aa365a0c95", 498 | "reference": "84b4dfb120c6f9b4ff7b3685f9b8f1aa365a0c95", 499 | "shasum": "" 500 | }, 501 | "require": { 502 | "php": "^7" 503 | }, 504 | "require-dev": { 505 | "phpunit/phpunit": "4.*|5.*", 506 | "vimeo/psalm": "^1" 507 | }, 508 | "suggest": { 509 | "ext-libsodium": "Provides a modern crypto API that can be used to generate random bytes." 510 | }, 511 | "type": "library", 512 | "notification-url": "https://packagist.org/downloads/", 513 | "license": [ 514 | "MIT" 515 | ], 516 | "authors": [ 517 | { 518 | "name": "Paragon Initiative Enterprises", 519 | "email": "security@paragonie.com", 520 | "homepage": "https://paragonie.com" 521 | } 522 | ], 523 | "description": "PHP 5.x polyfill for random_bytes() and random_int() from PHP 7", 524 | "keywords": [ 525 | "csprng", 526 | "polyfill", 527 | "pseudorandom", 528 | "random" 529 | ], 530 | "time": "2018-07-02T15:55:56+00:00" 531 | }, 532 | { 533 | "name": "php-cs-fixer/diff", 534 | "version": "v1.3.0", 535 | "source": { 536 | "type": "git", 537 | "url": "https://github.com/PHP-CS-Fixer/diff.git", 538 | "reference": "78bb099e9c16361126c86ce82ec4405ebab8e756" 539 | }, 540 | "dist": { 541 | "type": "zip", 542 | "url": "https://api.github.com/repos/PHP-CS-Fixer/diff/zipball/78bb099e9c16361126c86ce82ec4405ebab8e756", 543 | "reference": "78bb099e9c16361126c86ce82ec4405ebab8e756", 544 | "shasum": "" 545 | }, 546 | "require": { 547 | "php": "^5.6 || ^7.0" 548 | }, 549 | "require-dev": { 550 | "phpunit/phpunit": "^5.7.23 || ^6.4.3", 551 | "symfony/process": "^3.3" 552 | }, 553 | "type": "library", 554 | "autoload": { 555 | "classmap": [ 556 | "src/" 557 | ] 558 | }, 559 | "notification-url": "https://packagist.org/downloads/", 560 | "license": [ 561 | "BSD-3-Clause" 562 | ], 563 | "authors": [ 564 | { 565 | "name": "Kore Nordmann", 566 | "email": "mail@kore-nordmann.de" 567 | }, 568 | { 569 | "name": "Sebastian Bergmann", 570 | "email": "sebastian@phpunit.de" 571 | }, 572 | { 573 | "name": "SpacePossum" 574 | } 575 | ], 576 | "description": "sebastian/diff v2 backport support for PHP5.6", 577 | "homepage": "https://github.com/PHP-CS-Fixer", 578 | "keywords": [ 579 | "diff" 580 | ], 581 | "time": "2018-02-15T16:58:55+00:00" 582 | }, 583 | { 584 | "name": "phpdocumentor/reflection-common", 585 | "version": "2.0.0", 586 | "source": { 587 | "type": "git", 588 | "url": "https://github.com/phpDocumentor/ReflectionCommon.git", 589 | "reference": "63a995caa1ca9e5590304cd845c15ad6d482a62a" 590 | }, 591 | "dist": { 592 | "type": "zip", 593 | "url": "https://api.github.com/repos/phpDocumentor/ReflectionCommon/zipball/63a995caa1ca9e5590304cd845c15ad6d482a62a", 594 | "reference": "63a995caa1ca9e5590304cd845c15ad6d482a62a", 595 | "shasum": "" 596 | }, 597 | "require": { 598 | "php": ">=7.1" 599 | }, 600 | "require-dev": { 601 | "phpunit/phpunit": "~6" 602 | }, 603 | "type": "library", 604 | "extra": { 605 | "branch-alias": { 606 | "dev-master": "2.x-dev" 607 | } 608 | }, 609 | "autoload": { 610 | "psr-4": { 611 | "phpDocumentor\\Reflection\\": "src/" 612 | } 613 | }, 614 | "notification-url": "https://packagist.org/downloads/", 615 | "license": [ 616 | "MIT" 617 | ], 618 | "authors": [ 619 | { 620 | "name": "Jaap van Otterdijk", 621 | "email": "opensource@ijaap.nl" 622 | } 623 | ], 624 | "description": "Common reflection classes used by phpdocumentor to reflect the code structure", 625 | "homepage": "http://www.phpdoc.org", 626 | "keywords": [ 627 | "FQSEN", 628 | "phpDocumentor", 629 | "phpdoc", 630 | "reflection", 631 | "static analysis" 632 | ], 633 | "time": "2018-08-07T13:53:10+00:00" 634 | }, 635 | { 636 | "name": "phpdocumentor/reflection-docblock", 637 | "version": "5.1.0", 638 | "source": { 639 | "type": "git", 640 | "url": "https://github.com/phpDocumentor/ReflectionDocBlock.git", 641 | "reference": "cd72d394ca794d3466a3b2fc09d5a6c1dc86b47e" 642 | }, 643 | "dist": { 644 | "type": "zip", 645 | "url": "https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/cd72d394ca794d3466a3b2fc09d5a6c1dc86b47e", 646 | "reference": "cd72d394ca794d3466a3b2fc09d5a6c1dc86b47e", 647 | "shasum": "" 648 | }, 649 | "require": { 650 | "ext-filter": "^7.1", 651 | "php": "^7.2", 652 | "phpdocumentor/reflection-common": "^2.0", 653 | "phpdocumentor/type-resolver": "^1.0", 654 | "webmozart/assert": "^1" 655 | }, 656 | "require-dev": { 657 | "doctrine/instantiator": "^1", 658 | "mockery/mockery": "^1" 659 | }, 660 | "type": "library", 661 | "extra": { 662 | "branch-alias": { 663 | "dev-master": "5.x-dev" 664 | } 665 | }, 666 | "autoload": { 667 | "psr-4": { 668 | "phpDocumentor\\Reflection\\": "src" 669 | } 670 | }, 671 | "notification-url": "https://packagist.org/downloads/", 672 | "license": [ 673 | "MIT" 674 | ], 675 | "authors": [ 676 | { 677 | "name": "Mike van Riel", 678 | "email": "me@mikevanriel.com" 679 | }, 680 | { 681 | "name": "Jaap van Otterdijk", 682 | "email": "account@ijaap.nl" 683 | } 684 | ], 685 | "description": "With this component, a library can provide support for annotations via DocBlocks or otherwise retrieve information that is embedded in a DocBlock.", 686 | "time": "2020-02-22T12:28:44+00:00" 687 | }, 688 | { 689 | "name": "phpdocumentor/type-resolver", 690 | "version": "1.1.0", 691 | "source": { 692 | "type": "git", 693 | "url": "https://github.com/phpDocumentor/TypeResolver.git", 694 | "reference": "7462d5f123dfc080dfdf26897032a6513644fc95" 695 | }, 696 | "dist": { 697 | "type": "zip", 698 | "url": "https://api.github.com/repos/phpDocumentor/TypeResolver/zipball/7462d5f123dfc080dfdf26897032a6513644fc95", 699 | "reference": "7462d5f123dfc080dfdf26897032a6513644fc95", 700 | "shasum": "" 701 | }, 702 | "require": { 703 | "php": "^7.2", 704 | "phpdocumentor/reflection-common": "^2.0" 705 | }, 706 | "require-dev": { 707 | "ext-tokenizer": "^7.2", 708 | "mockery/mockery": "~1" 709 | }, 710 | "type": "library", 711 | "extra": { 712 | "branch-alias": { 713 | "dev-master": "1.x-dev" 714 | } 715 | }, 716 | "autoload": { 717 | "psr-4": { 718 | "phpDocumentor\\Reflection\\": "src" 719 | } 720 | }, 721 | "notification-url": "https://packagist.org/downloads/", 722 | "license": [ 723 | "MIT" 724 | ], 725 | "authors": [ 726 | { 727 | "name": "Mike van Riel", 728 | "email": "me@mikevanriel.com" 729 | } 730 | ], 731 | "description": "A PSR-5 based resolver of Class names, Types and Structural Element Names", 732 | "time": "2020-02-18T18:59:58+00:00" 733 | }, 734 | { 735 | "name": "phpspec/php-diff", 736 | "version": "v1.1.0", 737 | "source": { 738 | "type": "git", 739 | "url": "https://github.com/phpspec/php-diff.git", 740 | "reference": "0464787bfa7cd13576c5a1e318709768798bec6a" 741 | }, 742 | "dist": { 743 | "type": "zip", 744 | "url": "https://api.github.com/repos/phpspec/php-diff/zipball/0464787bfa7cd13576c5a1e318709768798bec6a", 745 | "reference": "0464787bfa7cd13576c5a1e318709768798bec6a", 746 | "shasum": "" 747 | }, 748 | "type": "library", 749 | "extra": { 750 | "branch-alias": { 751 | "dev-master": "1.0.x-dev" 752 | } 753 | }, 754 | "autoload": { 755 | "psr-0": { 756 | "Diff": "lib/" 757 | } 758 | }, 759 | "notification-url": "https://packagist.org/downloads/", 760 | "license": [ 761 | "BSD-3-Clause" 762 | ], 763 | "authors": [ 764 | { 765 | "name": "Chris Boulton", 766 | "homepage": "http://github.com/chrisboulton" 767 | } 768 | ], 769 | "description": "A comprehensive library for generating differences between two hashable objects (strings or arrays).", 770 | "time": "2016-04-07T12:29:16+00:00" 771 | }, 772 | { 773 | "name": "phpspec/phpspec", 774 | "version": "6.1.1", 775 | "source": { 776 | "type": "git", 777 | "url": "https://github.com/phpspec/phpspec.git", 778 | "reference": "486aaa736e9e24f3e22a6545f6affb88f98e2602" 779 | }, 780 | "dist": { 781 | "type": "zip", 782 | "url": "https://api.github.com/repos/phpspec/phpspec/zipball/486aaa736e9e24f3e22a6545f6affb88f98e2602", 783 | "reference": "486aaa736e9e24f3e22a6545f6affb88f98e2602", 784 | "shasum": "" 785 | }, 786 | "require": { 787 | "doctrine/instantiator": "^1.0.5", 788 | "ext-tokenizer": "*", 789 | "php": "^7.2, <7.5", 790 | "phpspec/php-diff": "^1.0.0", 791 | "phpspec/prophecy": "^1.9", 792 | "sebastian/exporter": "^1.0 || ^2.0 || ^3.0", 793 | "symfony/console": "^3.4 || ^4.0 || ^5.0", 794 | "symfony/event-dispatcher": "^3.4 || ^4.0 || ^5.0", 795 | "symfony/finder": "^3.4 || ^4.0 || ^5.0", 796 | "symfony/process": "^3.4 || ^4.0 || ^5.0", 797 | "symfony/yaml": "^3.4 || ^4.0 || ^5.0" 798 | }, 799 | "conflict": { 800 | "sebastian/comparator": "<1.2.4" 801 | }, 802 | "require-dev": { 803 | "behat/behat": "^3.3", 804 | "phpunit/phpunit": "^7.0", 805 | "symfony/filesystem": "^3.4 || ^4.0 || ^5.0" 806 | }, 807 | "suggest": { 808 | "phpspec/nyan-formatters": "Adds Nyan formatters" 809 | }, 810 | "bin": [ 811 | "bin/phpspec" 812 | ], 813 | "type": "library", 814 | "extra": { 815 | "branch-alias": { 816 | "dev-master": "6.1.x-dev" 817 | } 818 | }, 819 | "autoload": { 820 | "psr-0": { 821 | "PhpSpec": "src/" 822 | } 823 | }, 824 | "notification-url": "https://packagist.org/downloads/", 825 | "license": [ 826 | "MIT" 827 | ], 828 | "authors": [ 829 | { 830 | "name": "Konstantin Kudryashov", 831 | "email": "ever.zet@gmail.com", 832 | "homepage": "http://everzet.com" 833 | }, 834 | { 835 | "name": "Marcello Duarte", 836 | "homepage": "http://marcelloduarte.net/" 837 | }, 838 | { 839 | "name": "Ciaran McNulty", 840 | "homepage": "https://ciaranmcnulty.com/" 841 | } 842 | ], 843 | "description": "Specification-oriented BDD framework for PHP 7.1+", 844 | "homepage": "http://phpspec.net/", 845 | "keywords": [ 846 | "BDD", 847 | "SpecBDD", 848 | "TDD", 849 | "spec", 850 | "specification", 851 | "testing", 852 | "tests" 853 | ], 854 | "time": "2019-12-17T10:23:12+00:00" 855 | }, 856 | { 857 | "name": "phpspec/prophecy", 858 | "version": "v1.10.3", 859 | "source": { 860 | "type": "git", 861 | "url": "https://github.com/phpspec/prophecy.git", 862 | "reference": "451c3cd1418cf640de218914901e51b064abb093" 863 | }, 864 | "dist": { 865 | "type": "zip", 866 | "url": "https://api.github.com/repos/phpspec/prophecy/zipball/451c3cd1418cf640de218914901e51b064abb093", 867 | "reference": "451c3cd1418cf640de218914901e51b064abb093", 868 | "shasum": "" 869 | }, 870 | "require": { 871 | "doctrine/instantiator": "^1.0.2", 872 | "php": "^5.3|^7.0", 873 | "phpdocumentor/reflection-docblock": "^2.0|^3.0.2|^4.0|^5.0", 874 | "sebastian/comparator": "^1.2.3|^2.0|^3.0|^4.0", 875 | "sebastian/recursion-context": "^1.0|^2.0|^3.0|^4.0" 876 | }, 877 | "require-dev": { 878 | "phpspec/phpspec": "^2.5 || ^3.2", 879 | "phpunit/phpunit": "^4.8.35 || ^5.7 || ^6.5 || ^7.1" 880 | }, 881 | "type": "library", 882 | "extra": { 883 | "branch-alias": { 884 | "dev-master": "1.10.x-dev" 885 | } 886 | }, 887 | "autoload": { 888 | "psr-4": { 889 | "Prophecy\\": "src/Prophecy" 890 | } 891 | }, 892 | "notification-url": "https://packagist.org/downloads/", 893 | "license": [ 894 | "MIT" 895 | ], 896 | "authors": [ 897 | { 898 | "name": "Konstantin Kudryashov", 899 | "email": "ever.zet@gmail.com", 900 | "homepage": "http://everzet.com" 901 | }, 902 | { 903 | "name": "Marcello Duarte", 904 | "email": "marcello.duarte@gmail.com" 905 | } 906 | ], 907 | "description": "Highly opinionated mocking framework for PHP 5.3+", 908 | "homepage": "https://github.com/phpspec/prophecy", 909 | "keywords": [ 910 | "Double", 911 | "Dummy", 912 | "fake", 913 | "mock", 914 | "spy", 915 | "stub" 916 | ], 917 | "time": "2020-03-05T15:02:03+00:00" 918 | }, 919 | { 920 | "name": "phpunit/php-code-coverage", 921 | "version": "7.0.10", 922 | "source": { 923 | "type": "git", 924 | "url": "https://github.com/sebastianbergmann/php-code-coverage.git", 925 | "reference": "f1884187926fbb755a9aaf0b3836ad3165b478bf" 926 | }, 927 | "dist": { 928 | "type": "zip", 929 | "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/f1884187926fbb755a9aaf0b3836ad3165b478bf", 930 | "reference": "f1884187926fbb755a9aaf0b3836ad3165b478bf", 931 | "shasum": "" 932 | }, 933 | "require": { 934 | "ext-dom": "*", 935 | "ext-xmlwriter": "*", 936 | "php": "^7.2", 937 | "phpunit/php-file-iterator": "^2.0.2", 938 | "phpunit/php-text-template": "^1.2.1", 939 | "phpunit/php-token-stream": "^3.1.1", 940 | "sebastian/code-unit-reverse-lookup": "^1.0.1", 941 | "sebastian/environment": "^4.2.2", 942 | "sebastian/version": "^2.0.1", 943 | "theseer/tokenizer": "^1.1.3" 944 | }, 945 | "require-dev": { 946 | "phpunit/phpunit": "^8.2.2" 947 | }, 948 | "suggest": { 949 | "ext-xdebug": "^2.7.2" 950 | }, 951 | "type": "library", 952 | "extra": { 953 | "branch-alias": { 954 | "dev-master": "7.0-dev" 955 | } 956 | }, 957 | "autoload": { 958 | "classmap": [ 959 | "src/" 960 | ] 961 | }, 962 | "notification-url": "https://packagist.org/downloads/", 963 | "license": [ 964 | "BSD-3-Clause" 965 | ], 966 | "authors": [ 967 | { 968 | "name": "Sebastian Bergmann", 969 | "email": "sebastian@phpunit.de", 970 | "role": "lead" 971 | } 972 | ], 973 | "description": "Library that provides collection, processing, and rendering functionality for PHP code coverage information.", 974 | "homepage": "https://github.com/sebastianbergmann/php-code-coverage", 975 | "keywords": [ 976 | "coverage", 977 | "testing", 978 | "xunit" 979 | ], 980 | "time": "2019-11-20T13:55:58+00:00" 981 | }, 982 | { 983 | "name": "phpunit/php-file-iterator", 984 | "version": "2.0.2", 985 | "source": { 986 | "type": "git", 987 | "url": "https://github.com/sebastianbergmann/php-file-iterator.git", 988 | "reference": "050bedf145a257b1ff02746c31894800e5122946" 989 | }, 990 | "dist": { 991 | "type": "zip", 992 | "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/050bedf145a257b1ff02746c31894800e5122946", 993 | "reference": "050bedf145a257b1ff02746c31894800e5122946", 994 | "shasum": "" 995 | }, 996 | "require": { 997 | "php": "^7.1" 998 | }, 999 | "require-dev": { 1000 | "phpunit/phpunit": "^7.1" 1001 | }, 1002 | "type": "library", 1003 | "extra": { 1004 | "branch-alias": { 1005 | "dev-master": "2.0.x-dev" 1006 | } 1007 | }, 1008 | "autoload": { 1009 | "classmap": [ 1010 | "src/" 1011 | ] 1012 | }, 1013 | "notification-url": "https://packagist.org/downloads/", 1014 | "license": [ 1015 | "BSD-3-Clause" 1016 | ], 1017 | "authors": [ 1018 | { 1019 | "name": "Sebastian Bergmann", 1020 | "email": "sebastian@phpunit.de", 1021 | "role": "lead" 1022 | } 1023 | ], 1024 | "description": "FilterIterator implementation that filters files based on a list of suffixes.", 1025 | "homepage": "https://github.com/sebastianbergmann/php-file-iterator/", 1026 | "keywords": [ 1027 | "filesystem", 1028 | "iterator" 1029 | ], 1030 | "time": "2018-09-13T20:33:42+00:00" 1031 | }, 1032 | { 1033 | "name": "phpunit/php-text-template", 1034 | "version": "1.2.1", 1035 | "source": { 1036 | "type": "git", 1037 | "url": "https://github.com/sebastianbergmann/php-text-template.git", 1038 | "reference": "31f8b717e51d9a2afca6c9f046f5d69fc27c8686" 1039 | }, 1040 | "dist": { 1041 | "type": "zip", 1042 | "url": "https://api.github.com/repos/sebastianbergmann/php-text-template/zipball/31f8b717e51d9a2afca6c9f046f5d69fc27c8686", 1043 | "reference": "31f8b717e51d9a2afca6c9f046f5d69fc27c8686", 1044 | "shasum": "" 1045 | }, 1046 | "require": { 1047 | "php": ">=5.3.3" 1048 | }, 1049 | "type": "library", 1050 | "autoload": { 1051 | "classmap": [ 1052 | "src/" 1053 | ] 1054 | }, 1055 | "notification-url": "https://packagist.org/downloads/", 1056 | "license": [ 1057 | "BSD-3-Clause" 1058 | ], 1059 | "authors": [ 1060 | { 1061 | "name": "Sebastian Bergmann", 1062 | "email": "sebastian@phpunit.de", 1063 | "role": "lead" 1064 | } 1065 | ], 1066 | "description": "Simple template engine.", 1067 | "homepage": "https://github.com/sebastianbergmann/php-text-template/", 1068 | "keywords": [ 1069 | "template" 1070 | ], 1071 | "time": "2015-06-21T13:50:34+00:00" 1072 | }, 1073 | { 1074 | "name": "phpunit/php-token-stream", 1075 | "version": "3.1.1", 1076 | "source": { 1077 | "type": "git", 1078 | "url": "https://github.com/sebastianbergmann/php-token-stream.git", 1079 | "reference": "995192df77f63a59e47f025390d2d1fdf8f425ff" 1080 | }, 1081 | "dist": { 1082 | "type": "zip", 1083 | "url": "https://api.github.com/repos/sebastianbergmann/php-token-stream/zipball/995192df77f63a59e47f025390d2d1fdf8f425ff", 1084 | "reference": "995192df77f63a59e47f025390d2d1fdf8f425ff", 1085 | "shasum": "" 1086 | }, 1087 | "require": { 1088 | "ext-tokenizer": "*", 1089 | "php": "^7.1" 1090 | }, 1091 | "require-dev": { 1092 | "phpunit/phpunit": "^7.0" 1093 | }, 1094 | "type": "library", 1095 | "extra": { 1096 | "branch-alias": { 1097 | "dev-master": "3.1-dev" 1098 | } 1099 | }, 1100 | "autoload": { 1101 | "classmap": [ 1102 | "src/" 1103 | ] 1104 | }, 1105 | "notification-url": "https://packagist.org/downloads/", 1106 | "license": [ 1107 | "BSD-3-Clause" 1108 | ], 1109 | "authors": [ 1110 | { 1111 | "name": "Sebastian Bergmann", 1112 | "email": "sebastian@phpunit.de" 1113 | } 1114 | ], 1115 | "description": "Wrapper around PHP's tokenizer extension.", 1116 | "homepage": "https://github.com/sebastianbergmann/php-token-stream/", 1117 | "keywords": [ 1118 | "tokenizer" 1119 | ], 1120 | "time": "2019-09-17T06:23:10+00:00" 1121 | }, 1122 | { 1123 | "name": "psr/container", 1124 | "version": "1.0.0", 1125 | "source": { 1126 | "type": "git", 1127 | "url": "https://github.com/php-fig/container.git", 1128 | "reference": "b7ce3b176482dbbc1245ebf52b181af44c2cf55f" 1129 | }, 1130 | "dist": { 1131 | "type": "zip", 1132 | "url": "https://api.github.com/repos/php-fig/container/zipball/b7ce3b176482dbbc1245ebf52b181af44c2cf55f", 1133 | "reference": "b7ce3b176482dbbc1245ebf52b181af44c2cf55f", 1134 | "shasum": "" 1135 | }, 1136 | "require": { 1137 | "php": ">=5.3.0" 1138 | }, 1139 | "type": "library", 1140 | "extra": { 1141 | "branch-alias": { 1142 | "dev-master": "1.0.x-dev" 1143 | } 1144 | }, 1145 | "autoload": { 1146 | "psr-4": { 1147 | "Psr\\Container\\": "src/" 1148 | } 1149 | }, 1150 | "notification-url": "https://packagist.org/downloads/", 1151 | "license": [ 1152 | "MIT" 1153 | ], 1154 | "authors": [ 1155 | { 1156 | "name": "PHP-FIG", 1157 | "homepage": "http://www.php-fig.org/" 1158 | } 1159 | ], 1160 | "description": "Common Container Interface (PHP FIG PSR-11)", 1161 | "homepage": "https://github.com/php-fig/container", 1162 | "keywords": [ 1163 | "PSR-11", 1164 | "container", 1165 | "container-interface", 1166 | "container-interop", 1167 | "psr" 1168 | ], 1169 | "time": "2017-02-14T16:28:37+00:00" 1170 | }, 1171 | { 1172 | "name": "psr/event-dispatcher", 1173 | "version": "1.0.0", 1174 | "source": { 1175 | "type": "git", 1176 | "url": "https://github.com/php-fig/event-dispatcher.git", 1177 | "reference": "dbefd12671e8a14ec7f180cab83036ed26714bb0" 1178 | }, 1179 | "dist": { 1180 | "type": "zip", 1181 | "url": "https://api.github.com/repos/php-fig/event-dispatcher/zipball/dbefd12671e8a14ec7f180cab83036ed26714bb0", 1182 | "reference": "dbefd12671e8a14ec7f180cab83036ed26714bb0", 1183 | "shasum": "" 1184 | }, 1185 | "require": { 1186 | "php": ">=7.2.0" 1187 | }, 1188 | "type": "library", 1189 | "extra": { 1190 | "branch-alias": { 1191 | "dev-master": "1.0.x-dev" 1192 | } 1193 | }, 1194 | "autoload": { 1195 | "psr-4": { 1196 | "Psr\\EventDispatcher\\": "src/" 1197 | } 1198 | }, 1199 | "notification-url": "https://packagist.org/downloads/", 1200 | "license": [ 1201 | "MIT" 1202 | ], 1203 | "authors": [ 1204 | { 1205 | "name": "PHP-FIG", 1206 | "homepage": "http://www.php-fig.org/" 1207 | } 1208 | ], 1209 | "description": "Standard interfaces for event handling.", 1210 | "keywords": [ 1211 | "events", 1212 | "psr", 1213 | "psr-14" 1214 | ], 1215 | "time": "2019-01-08T18:20:26+00:00" 1216 | }, 1217 | { 1218 | "name": "psr/log", 1219 | "version": "1.1.3", 1220 | "source": { 1221 | "type": "git", 1222 | "url": "https://github.com/php-fig/log.git", 1223 | "reference": "0f73288fd15629204f9d42b7055f72dacbe811fc" 1224 | }, 1225 | "dist": { 1226 | "type": "zip", 1227 | "url": "https://api.github.com/repos/php-fig/log/zipball/0f73288fd15629204f9d42b7055f72dacbe811fc", 1228 | "reference": "0f73288fd15629204f9d42b7055f72dacbe811fc", 1229 | "shasum": "" 1230 | }, 1231 | "require": { 1232 | "php": ">=5.3.0" 1233 | }, 1234 | "type": "library", 1235 | "extra": { 1236 | "branch-alias": { 1237 | "dev-master": "1.1.x-dev" 1238 | } 1239 | }, 1240 | "autoload": { 1241 | "psr-4": { 1242 | "Psr\\Log\\": "Psr/Log/" 1243 | } 1244 | }, 1245 | "notification-url": "https://packagist.org/downloads/", 1246 | "license": [ 1247 | "MIT" 1248 | ], 1249 | "authors": [ 1250 | { 1251 | "name": "PHP-FIG", 1252 | "homepage": "http://www.php-fig.org/" 1253 | } 1254 | ], 1255 | "description": "Common interface for logging libraries", 1256 | "homepage": "https://github.com/php-fig/log", 1257 | "keywords": [ 1258 | "log", 1259 | "psr", 1260 | "psr-3" 1261 | ], 1262 | "time": "2020-03-23T09:12:05+00:00" 1263 | }, 1264 | { 1265 | "name": "sebastian/code-unit-reverse-lookup", 1266 | "version": "1.0.1", 1267 | "source": { 1268 | "type": "git", 1269 | "url": "https://github.com/sebastianbergmann/code-unit-reverse-lookup.git", 1270 | "reference": "4419fcdb5eabb9caa61a27c7a1db532a6b55dd18" 1271 | }, 1272 | "dist": { 1273 | "type": "zip", 1274 | "url": "https://api.github.com/repos/sebastianbergmann/code-unit-reverse-lookup/zipball/4419fcdb5eabb9caa61a27c7a1db532a6b55dd18", 1275 | "reference": "4419fcdb5eabb9caa61a27c7a1db532a6b55dd18", 1276 | "shasum": "" 1277 | }, 1278 | "require": { 1279 | "php": "^5.6 || ^7.0" 1280 | }, 1281 | "require-dev": { 1282 | "phpunit/phpunit": "^5.7 || ^6.0" 1283 | }, 1284 | "type": "library", 1285 | "extra": { 1286 | "branch-alias": { 1287 | "dev-master": "1.0.x-dev" 1288 | } 1289 | }, 1290 | "autoload": { 1291 | "classmap": [ 1292 | "src/" 1293 | ] 1294 | }, 1295 | "notification-url": "https://packagist.org/downloads/", 1296 | "license": [ 1297 | "BSD-3-Clause" 1298 | ], 1299 | "authors": [ 1300 | { 1301 | "name": "Sebastian Bergmann", 1302 | "email": "sebastian@phpunit.de" 1303 | } 1304 | ], 1305 | "description": "Looks up which function or method a line of code belongs to", 1306 | "homepage": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/", 1307 | "time": "2017-03-04T06:30:41+00:00" 1308 | }, 1309 | { 1310 | "name": "sebastian/comparator", 1311 | "version": "3.0.2", 1312 | "source": { 1313 | "type": "git", 1314 | "url": "https://github.com/sebastianbergmann/comparator.git", 1315 | "reference": "5de4fc177adf9bce8df98d8d141a7559d7ccf6da" 1316 | }, 1317 | "dist": { 1318 | "type": "zip", 1319 | "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/5de4fc177adf9bce8df98d8d141a7559d7ccf6da", 1320 | "reference": "5de4fc177adf9bce8df98d8d141a7559d7ccf6da", 1321 | "shasum": "" 1322 | }, 1323 | "require": { 1324 | "php": "^7.1", 1325 | "sebastian/diff": "^3.0", 1326 | "sebastian/exporter": "^3.1" 1327 | }, 1328 | "require-dev": { 1329 | "phpunit/phpunit": "^7.1" 1330 | }, 1331 | "type": "library", 1332 | "extra": { 1333 | "branch-alias": { 1334 | "dev-master": "3.0-dev" 1335 | } 1336 | }, 1337 | "autoload": { 1338 | "classmap": [ 1339 | "src/" 1340 | ] 1341 | }, 1342 | "notification-url": "https://packagist.org/downloads/", 1343 | "license": [ 1344 | "BSD-3-Clause" 1345 | ], 1346 | "authors": [ 1347 | { 1348 | "name": "Jeff Welch", 1349 | "email": "whatthejeff@gmail.com" 1350 | }, 1351 | { 1352 | "name": "Volker Dusch", 1353 | "email": "github@wallbash.com" 1354 | }, 1355 | { 1356 | "name": "Bernhard Schussek", 1357 | "email": "bschussek@2bepublished.at" 1358 | }, 1359 | { 1360 | "name": "Sebastian Bergmann", 1361 | "email": "sebastian@phpunit.de" 1362 | } 1363 | ], 1364 | "description": "Provides the functionality to compare PHP values for equality", 1365 | "homepage": "https://github.com/sebastianbergmann/comparator", 1366 | "keywords": [ 1367 | "comparator", 1368 | "compare", 1369 | "equality" 1370 | ], 1371 | "time": "2018-07-12T15:12:46+00:00" 1372 | }, 1373 | { 1374 | "name": "sebastian/diff", 1375 | "version": "3.0.2", 1376 | "source": { 1377 | "type": "git", 1378 | "url": "https://github.com/sebastianbergmann/diff.git", 1379 | "reference": "720fcc7e9b5cf384ea68d9d930d480907a0c1a29" 1380 | }, 1381 | "dist": { 1382 | "type": "zip", 1383 | "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/720fcc7e9b5cf384ea68d9d930d480907a0c1a29", 1384 | "reference": "720fcc7e9b5cf384ea68d9d930d480907a0c1a29", 1385 | "shasum": "" 1386 | }, 1387 | "require": { 1388 | "php": "^7.1" 1389 | }, 1390 | "require-dev": { 1391 | "phpunit/phpunit": "^7.5 || ^8.0", 1392 | "symfony/process": "^2 || ^3.3 || ^4" 1393 | }, 1394 | "type": "library", 1395 | "extra": { 1396 | "branch-alias": { 1397 | "dev-master": "3.0-dev" 1398 | } 1399 | }, 1400 | "autoload": { 1401 | "classmap": [ 1402 | "src/" 1403 | ] 1404 | }, 1405 | "notification-url": "https://packagist.org/downloads/", 1406 | "license": [ 1407 | "BSD-3-Clause" 1408 | ], 1409 | "authors": [ 1410 | { 1411 | "name": "Kore Nordmann", 1412 | "email": "mail@kore-nordmann.de" 1413 | }, 1414 | { 1415 | "name": "Sebastian Bergmann", 1416 | "email": "sebastian@phpunit.de" 1417 | } 1418 | ], 1419 | "description": "Diff implementation", 1420 | "homepage": "https://github.com/sebastianbergmann/diff", 1421 | "keywords": [ 1422 | "diff", 1423 | "udiff", 1424 | "unidiff", 1425 | "unified diff" 1426 | ], 1427 | "time": "2019-02-04T06:01:07+00:00" 1428 | }, 1429 | { 1430 | "name": "sebastian/environment", 1431 | "version": "4.2.3", 1432 | "source": { 1433 | "type": "git", 1434 | "url": "https://github.com/sebastianbergmann/environment.git", 1435 | "reference": "464c90d7bdf5ad4e8a6aea15c091fec0603d4368" 1436 | }, 1437 | "dist": { 1438 | "type": "zip", 1439 | "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/464c90d7bdf5ad4e8a6aea15c091fec0603d4368", 1440 | "reference": "464c90d7bdf5ad4e8a6aea15c091fec0603d4368", 1441 | "shasum": "" 1442 | }, 1443 | "require": { 1444 | "php": "^7.1" 1445 | }, 1446 | "require-dev": { 1447 | "phpunit/phpunit": "^7.5" 1448 | }, 1449 | "suggest": { 1450 | "ext-posix": "*" 1451 | }, 1452 | "type": "library", 1453 | "extra": { 1454 | "branch-alias": { 1455 | "dev-master": "4.2-dev" 1456 | } 1457 | }, 1458 | "autoload": { 1459 | "classmap": [ 1460 | "src/" 1461 | ] 1462 | }, 1463 | "notification-url": "https://packagist.org/downloads/", 1464 | "license": [ 1465 | "BSD-3-Clause" 1466 | ], 1467 | "authors": [ 1468 | { 1469 | "name": "Sebastian Bergmann", 1470 | "email": "sebastian@phpunit.de" 1471 | } 1472 | ], 1473 | "description": "Provides functionality to handle HHVM/PHP environments", 1474 | "homepage": "http://www.github.com/sebastianbergmann/environment", 1475 | "keywords": [ 1476 | "Xdebug", 1477 | "environment", 1478 | "hhvm" 1479 | ], 1480 | "time": "2019-11-20T08:46:58+00:00" 1481 | }, 1482 | { 1483 | "name": "sebastian/exporter", 1484 | "version": "3.1.2", 1485 | "source": { 1486 | "type": "git", 1487 | "url": "https://github.com/sebastianbergmann/exporter.git", 1488 | "reference": "68609e1261d215ea5b21b7987539cbfbe156ec3e" 1489 | }, 1490 | "dist": { 1491 | "type": "zip", 1492 | "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/68609e1261d215ea5b21b7987539cbfbe156ec3e", 1493 | "reference": "68609e1261d215ea5b21b7987539cbfbe156ec3e", 1494 | "shasum": "" 1495 | }, 1496 | "require": { 1497 | "php": "^7.0", 1498 | "sebastian/recursion-context": "^3.0" 1499 | }, 1500 | "require-dev": { 1501 | "ext-mbstring": "*", 1502 | "phpunit/phpunit": "^6.0" 1503 | }, 1504 | "type": "library", 1505 | "extra": { 1506 | "branch-alias": { 1507 | "dev-master": "3.1.x-dev" 1508 | } 1509 | }, 1510 | "autoload": { 1511 | "classmap": [ 1512 | "src/" 1513 | ] 1514 | }, 1515 | "notification-url": "https://packagist.org/downloads/", 1516 | "license": [ 1517 | "BSD-3-Clause" 1518 | ], 1519 | "authors": [ 1520 | { 1521 | "name": "Sebastian Bergmann", 1522 | "email": "sebastian@phpunit.de" 1523 | }, 1524 | { 1525 | "name": "Jeff Welch", 1526 | "email": "whatthejeff@gmail.com" 1527 | }, 1528 | { 1529 | "name": "Volker Dusch", 1530 | "email": "github@wallbash.com" 1531 | }, 1532 | { 1533 | "name": "Adam Harvey", 1534 | "email": "aharvey@php.net" 1535 | }, 1536 | { 1537 | "name": "Bernhard Schussek", 1538 | "email": "bschussek@gmail.com" 1539 | } 1540 | ], 1541 | "description": "Provides the functionality to export PHP variables for visualization", 1542 | "homepage": "http://www.github.com/sebastianbergmann/exporter", 1543 | "keywords": [ 1544 | "export", 1545 | "exporter" 1546 | ], 1547 | "time": "2019-09-14T09:02:43+00:00" 1548 | }, 1549 | { 1550 | "name": "sebastian/recursion-context", 1551 | "version": "3.0.0", 1552 | "source": { 1553 | "type": "git", 1554 | "url": "https://github.com/sebastianbergmann/recursion-context.git", 1555 | "reference": "5b0cd723502bac3b006cbf3dbf7a1e3fcefe4fa8" 1556 | }, 1557 | "dist": { 1558 | "type": "zip", 1559 | "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/5b0cd723502bac3b006cbf3dbf7a1e3fcefe4fa8", 1560 | "reference": "5b0cd723502bac3b006cbf3dbf7a1e3fcefe4fa8", 1561 | "shasum": "" 1562 | }, 1563 | "require": { 1564 | "php": "^7.0" 1565 | }, 1566 | "require-dev": { 1567 | "phpunit/phpunit": "^6.0" 1568 | }, 1569 | "type": "library", 1570 | "extra": { 1571 | "branch-alias": { 1572 | "dev-master": "3.0.x-dev" 1573 | } 1574 | }, 1575 | "autoload": { 1576 | "classmap": [ 1577 | "src/" 1578 | ] 1579 | }, 1580 | "notification-url": "https://packagist.org/downloads/", 1581 | "license": [ 1582 | "BSD-3-Clause" 1583 | ], 1584 | "authors": [ 1585 | { 1586 | "name": "Jeff Welch", 1587 | "email": "whatthejeff@gmail.com" 1588 | }, 1589 | { 1590 | "name": "Sebastian Bergmann", 1591 | "email": "sebastian@phpunit.de" 1592 | }, 1593 | { 1594 | "name": "Adam Harvey", 1595 | "email": "aharvey@php.net" 1596 | } 1597 | ], 1598 | "description": "Provides functionality to recursively process PHP variables", 1599 | "homepage": "http://www.github.com/sebastianbergmann/recursion-context", 1600 | "time": "2017-03-03T06:23:57+00:00" 1601 | }, 1602 | { 1603 | "name": "sebastian/version", 1604 | "version": "2.0.1", 1605 | "source": { 1606 | "type": "git", 1607 | "url": "https://github.com/sebastianbergmann/version.git", 1608 | "reference": "99732be0ddb3361e16ad77b68ba41efc8e979019" 1609 | }, 1610 | "dist": { 1611 | "type": "zip", 1612 | "url": "https://api.github.com/repos/sebastianbergmann/version/zipball/99732be0ddb3361e16ad77b68ba41efc8e979019", 1613 | "reference": "99732be0ddb3361e16ad77b68ba41efc8e979019", 1614 | "shasum": "" 1615 | }, 1616 | "require": { 1617 | "php": ">=5.6" 1618 | }, 1619 | "type": "library", 1620 | "extra": { 1621 | "branch-alias": { 1622 | "dev-master": "2.0.x-dev" 1623 | } 1624 | }, 1625 | "autoload": { 1626 | "classmap": [ 1627 | "src/" 1628 | ] 1629 | }, 1630 | "notification-url": "https://packagist.org/downloads/", 1631 | "license": [ 1632 | "BSD-3-Clause" 1633 | ], 1634 | "authors": [ 1635 | { 1636 | "name": "Sebastian Bergmann", 1637 | "email": "sebastian@phpunit.de", 1638 | "role": "lead" 1639 | } 1640 | ], 1641 | "description": "Library that helps with managing the version number of Git-hosted PHP projects", 1642 | "homepage": "https://github.com/sebastianbergmann/version", 1643 | "time": "2016-10-03T07:35:21+00:00" 1644 | }, 1645 | { 1646 | "name": "symfony/console", 1647 | "version": "v5.0.7", 1648 | "source": { 1649 | "type": "git", 1650 | "url": "https://github.com/symfony/console.git", 1651 | "reference": "5fa1caadc8cdaa17bcfb25219f3b53fe294a9935" 1652 | }, 1653 | "dist": { 1654 | "type": "zip", 1655 | "url": "https://api.github.com/repos/symfony/console/zipball/5fa1caadc8cdaa17bcfb25219f3b53fe294a9935", 1656 | "reference": "5fa1caadc8cdaa17bcfb25219f3b53fe294a9935", 1657 | "shasum": "" 1658 | }, 1659 | "require": { 1660 | "php": "^7.2.5", 1661 | "symfony/polyfill-mbstring": "~1.0", 1662 | "symfony/polyfill-php73": "^1.8", 1663 | "symfony/service-contracts": "^1.1|^2" 1664 | }, 1665 | "conflict": { 1666 | "symfony/dependency-injection": "<4.4", 1667 | "symfony/event-dispatcher": "<4.4", 1668 | "symfony/lock": "<4.4", 1669 | "symfony/process": "<4.4" 1670 | }, 1671 | "provide": { 1672 | "psr/log-implementation": "1.0" 1673 | }, 1674 | "require-dev": { 1675 | "psr/log": "~1.0", 1676 | "symfony/config": "^4.4|^5.0", 1677 | "symfony/dependency-injection": "^4.4|^5.0", 1678 | "symfony/event-dispatcher": "^4.4|^5.0", 1679 | "symfony/lock": "^4.4|^5.0", 1680 | "symfony/process": "^4.4|^5.0", 1681 | "symfony/var-dumper": "^4.4|^5.0" 1682 | }, 1683 | "suggest": { 1684 | "psr/log": "For using the console logger", 1685 | "symfony/event-dispatcher": "", 1686 | "symfony/lock": "", 1687 | "symfony/process": "" 1688 | }, 1689 | "type": "library", 1690 | "extra": { 1691 | "branch-alias": { 1692 | "dev-master": "5.0-dev" 1693 | } 1694 | }, 1695 | "autoload": { 1696 | "psr-4": { 1697 | "Symfony\\Component\\Console\\": "" 1698 | }, 1699 | "exclude-from-classmap": [ 1700 | "/Tests/" 1701 | ] 1702 | }, 1703 | "notification-url": "https://packagist.org/downloads/", 1704 | "license": [ 1705 | "MIT" 1706 | ], 1707 | "authors": [ 1708 | { 1709 | "name": "Fabien Potencier", 1710 | "email": "fabien@symfony.com" 1711 | }, 1712 | { 1713 | "name": "Symfony Community", 1714 | "homepage": "https://symfony.com/contributors" 1715 | } 1716 | ], 1717 | "description": "Symfony Console Component", 1718 | "homepage": "https://symfony.com", 1719 | "funding": [ 1720 | { 1721 | "url": "https://symfony.com/sponsor", 1722 | "type": "custom" 1723 | }, 1724 | { 1725 | "url": "https://github.com/fabpot", 1726 | "type": "github" 1727 | }, 1728 | { 1729 | "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", 1730 | "type": "tidelift" 1731 | } 1732 | ], 1733 | "time": "2020-03-30T11:42:42+00:00" 1734 | }, 1735 | { 1736 | "name": "symfony/event-dispatcher", 1737 | "version": "v5.0.7", 1738 | "source": { 1739 | "type": "git", 1740 | "url": "https://github.com/symfony/event-dispatcher.git", 1741 | "reference": "24f40d95385774ed5c71dbf014edd047e2f2f3dc" 1742 | }, 1743 | "dist": { 1744 | "type": "zip", 1745 | "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/24f40d95385774ed5c71dbf014edd047e2f2f3dc", 1746 | "reference": "24f40d95385774ed5c71dbf014edd047e2f2f3dc", 1747 | "shasum": "" 1748 | }, 1749 | "require": { 1750 | "php": "^7.2.5", 1751 | "symfony/event-dispatcher-contracts": "^2" 1752 | }, 1753 | "conflict": { 1754 | "symfony/dependency-injection": "<4.4" 1755 | }, 1756 | "provide": { 1757 | "psr/event-dispatcher-implementation": "1.0", 1758 | "symfony/event-dispatcher-implementation": "2.0" 1759 | }, 1760 | "require-dev": { 1761 | "psr/log": "~1.0", 1762 | "symfony/config": "^4.4|^5.0", 1763 | "symfony/dependency-injection": "^4.4|^5.0", 1764 | "symfony/expression-language": "^4.4|^5.0", 1765 | "symfony/http-foundation": "^4.4|^5.0", 1766 | "symfony/service-contracts": "^1.1|^2", 1767 | "symfony/stopwatch": "^4.4|^5.0" 1768 | }, 1769 | "suggest": { 1770 | "symfony/dependency-injection": "", 1771 | "symfony/http-kernel": "" 1772 | }, 1773 | "type": "library", 1774 | "extra": { 1775 | "branch-alias": { 1776 | "dev-master": "5.0-dev" 1777 | } 1778 | }, 1779 | "autoload": { 1780 | "psr-4": { 1781 | "Symfony\\Component\\EventDispatcher\\": "" 1782 | }, 1783 | "exclude-from-classmap": [ 1784 | "/Tests/" 1785 | ] 1786 | }, 1787 | "notification-url": "https://packagist.org/downloads/", 1788 | "license": [ 1789 | "MIT" 1790 | ], 1791 | "authors": [ 1792 | { 1793 | "name": "Fabien Potencier", 1794 | "email": "fabien@symfony.com" 1795 | }, 1796 | { 1797 | "name": "Symfony Community", 1798 | "homepage": "https://symfony.com/contributors" 1799 | } 1800 | ], 1801 | "description": "Symfony EventDispatcher Component", 1802 | "homepage": "https://symfony.com", 1803 | "funding": [ 1804 | { 1805 | "url": "https://symfony.com/sponsor", 1806 | "type": "custom" 1807 | }, 1808 | { 1809 | "url": "https://github.com/fabpot", 1810 | "type": "github" 1811 | }, 1812 | { 1813 | "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", 1814 | "type": "tidelift" 1815 | } 1816 | ], 1817 | "time": "2020-03-27T16:56:45+00:00" 1818 | }, 1819 | { 1820 | "name": "symfony/event-dispatcher-contracts", 1821 | "version": "v2.0.1", 1822 | "source": { 1823 | "type": "git", 1824 | "url": "https://github.com/symfony/event-dispatcher-contracts.git", 1825 | "reference": "af23c2584d4577d54661c434446fb8fbed6025dd" 1826 | }, 1827 | "dist": { 1828 | "type": "zip", 1829 | "url": "https://api.github.com/repos/symfony/event-dispatcher-contracts/zipball/af23c2584d4577d54661c434446fb8fbed6025dd", 1830 | "reference": "af23c2584d4577d54661c434446fb8fbed6025dd", 1831 | "shasum": "" 1832 | }, 1833 | "require": { 1834 | "php": "^7.2.5", 1835 | "psr/event-dispatcher": "^1" 1836 | }, 1837 | "suggest": { 1838 | "symfony/event-dispatcher-implementation": "" 1839 | }, 1840 | "type": "library", 1841 | "extra": { 1842 | "branch-alias": { 1843 | "dev-master": "2.0-dev" 1844 | } 1845 | }, 1846 | "autoload": { 1847 | "psr-4": { 1848 | "Symfony\\Contracts\\EventDispatcher\\": "" 1849 | } 1850 | }, 1851 | "notification-url": "https://packagist.org/downloads/", 1852 | "license": [ 1853 | "MIT" 1854 | ], 1855 | "authors": [ 1856 | { 1857 | "name": "Nicolas Grekas", 1858 | "email": "p@tchwork.com" 1859 | }, 1860 | { 1861 | "name": "Symfony Community", 1862 | "homepage": "https://symfony.com/contributors" 1863 | } 1864 | ], 1865 | "description": "Generic abstractions related to dispatching event", 1866 | "homepage": "https://symfony.com", 1867 | "keywords": [ 1868 | "abstractions", 1869 | "contracts", 1870 | "decoupling", 1871 | "interfaces", 1872 | "interoperability", 1873 | "standards" 1874 | ], 1875 | "time": "2019-11-18T17:27:11+00:00" 1876 | }, 1877 | { 1878 | "name": "symfony/filesystem", 1879 | "version": "v5.0.7", 1880 | "source": { 1881 | "type": "git", 1882 | "url": "https://github.com/symfony/filesystem.git", 1883 | "reference": "ca3b87dd09fff9b771731637f5379965fbfab420" 1884 | }, 1885 | "dist": { 1886 | "type": "zip", 1887 | "url": "https://api.github.com/repos/symfony/filesystem/zipball/ca3b87dd09fff9b771731637f5379965fbfab420", 1888 | "reference": "ca3b87dd09fff9b771731637f5379965fbfab420", 1889 | "shasum": "" 1890 | }, 1891 | "require": { 1892 | "php": "^7.2.5", 1893 | "symfony/polyfill-ctype": "~1.8" 1894 | }, 1895 | "type": "library", 1896 | "extra": { 1897 | "branch-alias": { 1898 | "dev-master": "5.0-dev" 1899 | } 1900 | }, 1901 | "autoload": { 1902 | "psr-4": { 1903 | "Symfony\\Component\\Filesystem\\": "" 1904 | }, 1905 | "exclude-from-classmap": [ 1906 | "/Tests/" 1907 | ] 1908 | }, 1909 | "notification-url": "https://packagist.org/downloads/", 1910 | "license": [ 1911 | "MIT" 1912 | ], 1913 | "authors": [ 1914 | { 1915 | "name": "Fabien Potencier", 1916 | "email": "fabien@symfony.com" 1917 | }, 1918 | { 1919 | "name": "Symfony Community", 1920 | "homepage": "https://symfony.com/contributors" 1921 | } 1922 | ], 1923 | "description": "Symfony Filesystem Component", 1924 | "homepage": "https://symfony.com", 1925 | "funding": [ 1926 | { 1927 | "url": "https://symfony.com/sponsor", 1928 | "type": "custom" 1929 | }, 1930 | { 1931 | "url": "https://github.com/fabpot", 1932 | "type": "github" 1933 | }, 1934 | { 1935 | "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", 1936 | "type": "tidelift" 1937 | } 1938 | ], 1939 | "time": "2020-03-27T16:56:45+00:00" 1940 | }, 1941 | { 1942 | "name": "symfony/finder", 1943 | "version": "v5.0.7", 1944 | "source": { 1945 | "type": "git", 1946 | "url": "https://github.com/symfony/finder.git", 1947 | "reference": "600a52c29afc0d1caa74acbec8d3095ca7e9910d" 1948 | }, 1949 | "dist": { 1950 | "type": "zip", 1951 | "url": "https://api.github.com/repos/symfony/finder/zipball/600a52c29afc0d1caa74acbec8d3095ca7e9910d", 1952 | "reference": "600a52c29afc0d1caa74acbec8d3095ca7e9910d", 1953 | "shasum": "" 1954 | }, 1955 | "require": { 1956 | "php": "^7.2.5" 1957 | }, 1958 | "type": "library", 1959 | "extra": { 1960 | "branch-alias": { 1961 | "dev-master": "5.0-dev" 1962 | } 1963 | }, 1964 | "autoload": { 1965 | "psr-4": { 1966 | "Symfony\\Component\\Finder\\": "" 1967 | }, 1968 | "exclude-from-classmap": [ 1969 | "/Tests/" 1970 | ] 1971 | }, 1972 | "notification-url": "https://packagist.org/downloads/", 1973 | "license": [ 1974 | "MIT" 1975 | ], 1976 | "authors": [ 1977 | { 1978 | "name": "Fabien Potencier", 1979 | "email": "fabien@symfony.com" 1980 | }, 1981 | { 1982 | "name": "Symfony Community", 1983 | "homepage": "https://symfony.com/contributors" 1984 | } 1985 | ], 1986 | "description": "Symfony Finder Component", 1987 | "homepage": "https://symfony.com", 1988 | "funding": [ 1989 | { 1990 | "url": "https://symfony.com/sponsor", 1991 | "type": "custom" 1992 | }, 1993 | { 1994 | "url": "https://github.com/fabpot", 1995 | "type": "github" 1996 | }, 1997 | { 1998 | "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", 1999 | "type": "tidelift" 2000 | } 2001 | ], 2002 | "time": "2020-03-27T16:56:45+00:00" 2003 | }, 2004 | { 2005 | "name": "symfony/options-resolver", 2006 | "version": "v5.0.7", 2007 | "source": { 2008 | "type": "git", 2009 | "url": "https://github.com/symfony/options-resolver.git", 2010 | "reference": "09dccfffd24b311df7f184aa80ee7b61ad61ed8d" 2011 | }, 2012 | "dist": { 2013 | "type": "zip", 2014 | "url": "https://api.github.com/repos/symfony/options-resolver/zipball/09dccfffd24b311df7f184aa80ee7b61ad61ed8d", 2015 | "reference": "09dccfffd24b311df7f184aa80ee7b61ad61ed8d", 2016 | "shasum": "" 2017 | }, 2018 | "require": { 2019 | "php": "^7.2.5" 2020 | }, 2021 | "type": "library", 2022 | "extra": { 2023 | "branch-alias": { 2024 | "dev-master": "5.0-dev" 2025 | } 2026 | }, 2027 | "autoload": { 2028 | "psr-4": { 2029 | "Symfony\\Component\\OptionsResolver\\": "" 2030 | }, 2031 | "exclude-from-classmap": [ 2032 | "/Tests/" 2033 | ] 2034 | }, 2035 | "notification-url": "https://packagist.org/downloads/", 2036 | "license": [ 2037 | "MIT" 2038 | ], 2039 | "authors": [ 2040 | { 2041 | "name": "Fabien Potencier", 2042 | "email": "fabien@symfony.com" 2043 | }, 2044 | { 2045 | "name": "Symfony Community", 2046 | "homepage": "https://symfony.com/contributors" 2047 | } 2048 | ], 2049 | "description": "Symfony OptionsResolver Component", 2050 | "homepage": "https://symfony.com", 2051 | "keywords": [ 2052 | "config", 2053 | "configuration", 2054 | "options" 2055 | ], 2056 | "funding": [ 2057 | { 2058 | "url": "https://symfony.com/sponsor", 2059 | "type": "custom" 2060 | }, 2061 | { 2062 | "url": "https://github.com/fabpot", 2063 | "type": "github" 2064 | }, 2065 | { 2066 | "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", 2067 | "type": "tidelift" 2068 | } 2069 | ], 2070 | "time": "2020-03-27T16:56:45+00:00" 2071 | }, 2072 | { 2073 | "name": "symfony/polyfill-ctype", 2074 | "version": "v1.15.0", 2075 | "source": { 2076 | "type": "git", 2077 | "url": "https://github.com/symfony/polyfill-ctype.git", 2078 | "reference": "4719fa9c18b0464d399f1a63bf624b42b6fa8d14" 2079 | }, 2080 | "dist": { 2081 | "type": "zip", 2082 | "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/4719fa9c18b0464d399f1a63bf624b42b6fa8d14", 2083 | "reference": "4719fa9c18b0464d399f1a63bf624b42b6fa8d14", 2084 | "shasum": "" 2085 | }, 2086 | "require": { 2087 | "php": ">=5.3.3" 2088 | }, 2089 | "suggest": { 2090 | "ext-ctype": "For best performance" 2091 | }, 2092 | "type": "library", 2093 | "extra": { 2094 | "branch-alias": { 2095 | "dev-master": "1.15-dev" 2096 | } 2097 | }, 2098 | "autoload": { 2099 | "psr-4": { 2100 | "Symfony\\Polyfill\\Ctype\\": "" 2101 | }, 2102 | "files": [ 2103 | "bootstrap.php" 2104 | ] 2105 | }, 2106 | "notification-url": "https://packagist.org/downloads/", 2107 | "license": [ 2108 | "MIT" 2109 | ], 2110 | "authors": [ 2111 | { 2112 | "name": "Gert de Pagter", 2113 | "email": "BackEndTea@gmail.com" 2114 | }, 2115 | { 2116 | "name": "Symfony Community", 2117 | "homepage": "https://symfony.com/contributors" 2118 | } 2119 | ], 2120 | "description": "Symfony polyfill for ctype functions", 2121 | "homepage": "https://symfony.com", 2122 | "keywords": [ 2123 | "compatibility", 2124 | "ctype", 2125 | "polyfill", 2126 | "portable" 2127 | ], 2128 | "funding": [ 2129 | { 2130 | "url": "https://symfony.com/sponsor", 2131 | "type": "custom" 2132 | }, 2133 | { 2134 | "url": "https://github.com/fabpot", 2135 | "type": "github" 2136 | }, 2137 | { 2138 | "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", 2139 | "type": "tidelift" 2140 | } 2141 | ], 2142 | "time": "2020-02-27T09:26:54+00:00" 2143 | }, 2144 | { 2145 | "name": "symfony/polyfill-mbstring", 2146 | "version": "v1.15.0", 2147 | "source": { 2148 | "type": "git", 2149 | "url": "https://github.com/symfony/polyfill-mbstring.git", 2150 | "reference": "81ffd3a9c6d707be22e3012b827de1c9775fc5ac" 2151 | }, 2152 | "dist": { 2153 | "type": "zip", 2154 | "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/81ffd3a9c6d707be22e3012b827de1c9775fc5ac", 2155 | "reference": "81ffd3a9c6d707be22e3012b827de1c9775fc5ac", 2156 | "shasum": "" 2157 | }, 2158 | "require": { 2159 | "php": ">=5.3.3" 2160 | }, 2161 | "suggest": { 2162 | "ext-mbstring": "For best performance" 2163 | }, 2164 | "type": "library", 2165 | "extra": { 2166 | "branch-alias": { 2167 | "dev-master": "1.15-dev" 2168 | } 2169 | }, 2170 | "autoload": { 2171 | "psr-4": { 2172 | "Symfony\\Polyfill\\Mbstring\\": "" 2173 | }, 2174 | "files": [ 2175 | "bootstrap.php" 2176 | ] 2177 | }, 2178 | "notification-url": "https://packagist.org/downloads/", 2179 | "license": [ 2180 | "MIT" 2181 | ], 2182 | "authors": [ 2183 | { 2184 | "name": "Nicolas Grekas", 2185 | "email": "p@tchwork.com" 2186 | }, 2187 | { 2188 | "name": "Symfony Community", 2189 | "homepage": "https://symfony.com/contributors" 2190 | } 2191 | ], 2192 | "description": "Symfony polyfill for the Mbstring extension", 2193 | "homepage": "https://symfony.com", 2194 | "keywords": [ 2195 | "compatibility", 2196 | "mbstring", 2197 | "polyfill", 2198 | "portable", 2199 | "shim" 2200 | ], 2201 | "funding": [ 2202 | { 2203 | "url": "https://symfony.com/sponsor", 2204 | "type": "custom" 2205 | }, 2206 | { 2207 | "url": "https://github.com/fabpot", 2208 | "type": "github" 2209 | }, 2210 | { 2211 | "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", 2212 | "type": "tidelift" 2213 | } 2214 | ], 2215 | "time": "2020-03-09T19:04:49+00:00" 2216 | }, 2217 | { 2218 | "name": "symfony/polyfill-php70", 2219 | "version": "v1.15.0", 2220 | "source": { 2221 | "type": "git", 2222 | "url": "https://github.com/symfony/polyfill-php70.git", 2223 | "reference": "2a18e37a489803559284416df58c71ccebe50bf0" 2224 | }, 2225 | "dist": { 2226 | "type": "zip", 2227 | "url": "https://api.github.com/repos/symfony/polyfill-php70/zipball/2a18e37a489803559284416df58c71ccebe50bf0", 2228 | "reference": "2a18e37a489803559284416df58c71ccebe50bf0", 2229 | "shasum": "" 2230 | }, 2231 | "require": { 2232 | "paragonie/random_compat": "~1.0|~2.0|~9.99", 2233 | "php": ">=5.3.3" 2234 | }, 2235 | "type": "library", 2236 | "extra": { 2237 | "branch-alias": { 2238 | "dev-master": "1.15-dev" 2239 | } 2240 | }, 2241 | "autoload": { 2242 | "psr-4": { 2243 | "Symfony\\Polyfill\\Php70\\": "" 2244 | }, 2245 | "files": [ 2246 | "bootstrap.php" 2247 | ], 2248 | "classmap": [ 2249 | "Resources/stubs" 2250 | ] 2251 | }, 2252 | "notification-url": "https://packagist.org/downloads/", 2253 | "license": [ 2254 | "MIT" 2255 | ], 2256 | "authors": [ 2257 | { 2258 | "name": "Nicolas Grekas", 2259 | "email": "p@tchwork.com" 2260 | }, 2261 | { 2262 | "name": "Symfony Community", 2263 | "homepage": "https://symfony.com/contributors" 2264 | } 2265 | ], 2266 | "description": "Symfony polyfill backporting some PHP 7.0+ features to lower PHP versions", 2267 | "homepage": "https://symfony.com", 2268 | "keywords": [ 2269 | "compatibility", 2270 | "polyfill", 2271 | "portable", 2272 | "shim" 2273 | ], 2274 | "time": "2020-02-27T09:26:54+00:00" 2275 | }, 2276 | { 2277 | "name": "symfony/polyfill-php72", 2278 | "version": "v1.15.0", 2279 | "source": { 2280 | "type": "git", 2281 | "url": "https://github.com/symfony/polyfill-php72.git", 2282 | "reference": "37b0976c78b94856543260ce09b460a7bc852747" 2283 | }, 2284 | "dist": { 2285 | "type": "zip", 2286 | "url": "https://api.github.com/repos/symfony/polyfill-php72/zipball/37b0976c78b94856543260ce09b460a7bc852747", 2287 | "reference": "37b0976c78b94856543260ce09b460a7bc852747", 2288 | "shasum": "" 2289 | }, 2290 | "require": { 2291 | "php": ">=5.3.3" 2292 | }, 2293 | "type": "library", 2294 | "extra": { 2295 | "branch-alias": { 2296 | "dev-master": "1.15-dev" 2297 | } 2298 | }, 2299 | "autoload": { 2300 | "psr-4": { 2301 | "Symfony\\Polyfill\\Php72\\": "" 2302 | }, 2303 | "files": [ 2304 | "bootstrap.php" 2305 | ] 2306 | }, 2307 | "notification-url": "https://packagist.org/downloads/", 2308 | "license": [ 2309 | "MIT" 2310 | ], 2311 | "authors": [ 2312 | { 2313 | "name": "Nicolas Grekas", 2314 | "email": "p@tchwork.com" 2315 | }, 2316 | { 2317 | "name": "Symfony Community", 2318 | "homepage": "https://symfony.com/contributors" 2319 | } 2320 | ], 2321 | "description": "Symfony polyfill backporting some PHP 7.2+ features to lower PHP versions", 2322 | "homepage": "https://symfony.com", 2323 | "keywords": [ 2324 | "compatibility", 2325 | "polyfill", 2326 | "portable", 2327 | "shim" 2328 | ], 2329 | "funding": [ 2330 | { 2331 | "url": "https://symfony.com/sponsor", 2332 | "type": "custom" 2333 | }, 2334 | { 2335 | "url": "https://github.com/fabpot", 2336 | "type": "github" 2337 | }, 2338 | { 2339 | "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", 2340 | "type": "tidelift" 2341 | } 2342 | ], 2343 | "time": "2020-02-27T09:26:54+00:00" 2344 | }, 2345 | { 2346 | "name": "symfony/polyfill-php73", 2347 | "version": "v1.15.0", 2348 | "source": { 2349 | "type": "git", 2350 | "url": "https://github.com/symfony/polyfill-php73.git", 2351 | "reference": "0f27e9f464ea3da33cbe7ca3bdf4eb66def9d0f7" 2352 | }, 2353 | "dist": { 2354 | "type": "zip", 2355 | "url": "https://api.github.com/repos/symfony/polyfill-php73/zipball/0f27e9f464ea3da33cbe7ca3bdf4eb66def9d0f7", 2356 | "reference": "0f27e9f464ea3da33cbe7ca3bdf4eb66def9d0f7", 2357 | "shasum": "" 2358 | }, 2359 | "require": { 2360 | "php": ">=5.3.3" 2361 | }, 2362 | "type": "library", 2363 | "extra": { 2364 | "branch-alias": { 2365 | "dev-master": "1.15-dev" 2366 | } 2367 | }, 2368 | "autoload": { 2369 | "psr-4": { 2370 | "Symfony\\Polyfill\\Php73\\": "" 2371 | }, 2372 | "files": [ 2373 | "bootstrap.php" 2374 | ], 2375 | "classmap": [ 2376 | "Resources/stubs" 2377 | ] 2378 | }, 2379 | "notification-url": "https://packagist.org/downloads/", 2380 | "license": [ 2381 | "MIT" 2382 | ], 2383 | "authors": [ 2384 | { 2385 | "name": "Nicolas Grekas", 2386 | "email": "p@tchwork.com" 2387 | }, 2388 | { 2389 | "name": "Symfony Community", 2390 | "homepage": "https://symfony.com/contributors" 2391 | } 2392 | ], 2393 | "description": "Symfony polyfill backporting some PHP 7.3+ features to lower PHP versions", 2394 | "homepage": "https://symfony.com", 2395 | "keywords": [ 2396 | "compatibility", 2397 | "polyfill", 2398 | "portable", 2399 | "shim" 2400 | ], 2401 | "funding": [ 2402 | { 2403 | "url": "https://symfony.com/sponsor", 2404 | "type": "custom" 2405 | }, 2406 | { 2407 | "url": "https://github.com/fabpot", 2408 | "type": "github" 2409 | }, 2410 | { 2411 | "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", 2412 | "type": "tidelift" 2413 | } 2414 | ], 2415 | "time": "2020-02-27T09:26:54+00:00" 2416 | }, 2417 | { 2418 | "name": "symfony/process", 2419 | "version": "v5.0.7", 2420 | "source": { 2421 | "type": "git", 2422 | "url": "https://github.com/symfony/process.git", 2423 | "reference": "c5ca4a0fc16a0c888067d43fbcfe1f8a53d8e70e" 2424 | }, 2425 | "dist": { 2426 | "type": "zip", 2427 | "url": "https://api.github.com/repos/symfony/process/zipball/c5ca4a0fc16a0c888067d43fbcfe1f8a53d8e70e", 2428 | "reference": "c5ca4a0fc16a0c888067d43fbcfe1f8a53d8e70e", 2429 | "shasum": "" 2430 | }, 2431 | "require": { 2432 | "php": "^7.2.5" 2433 | }, 2434 | "type": "library", 2435 | "extra": { 2436 | "branch-alias": { 2437 | "dev-master": "5.0-dev" 2438 | } 2439 | }, 2440 | "autoload": { 2441 | "psr-4": { 2442 | "Symfony\\Component\\Process\\": "" 2443 | }, 2444 | "exclude-from-classmap": [ 2445 | "/Tests/" 2446 | ] 2447 | }, 2448 | "notification-url": "https://packagist.org/downloads/", 2449 | "license": [ 2450 | "MIT" 2451 | ], 2452 | "authors": [ 2453 | { 2454 | "name": "Fabien Potencier", 2455 | "email": "fabien@symfony.com" 2456 | }, 2457 | { 2458 | "name": "Symfony Community", 2459 | "homepage": "https://symfony.com/contributors" 2460 | } 2461 | ], 2462 | "description": "Symfony Process Component", 2463 | "homepage": "https://symfony.com", 2464 | "funding": [ 2465 | { 2466 | "url": "https://symfony.com/sponsor", 2467 | "type": "custom" 2468 | }, 2469 | { 2470 | "url": "https://github.com/fabpot", 2471 | "type": "github" 2472 | }, 2473 | { 2474 | "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", 2475 | "type": "tidelift" 2476 | } 2477 | ], 2478 | "time": "2020-03-27T16:56:45+00:00" 2479 | }, 2480 | { 2481 | "name": "symfony/service-contracts", 2482 | "version": "v2.0.1", 2483 | "source": { 2484 | "type": "git", 2485 | "url": "https://github.com/symfony/service-contracts.git", 2486 | "reference": "144c5e51266b281231e947b51223ba14acf1a749" 2487 | }, 2488 | "dist": { 2489 | "type": "zip", 2490 | "url": "https://api.github.com/repos/symfony/service-contracts/zipball/144c5e51266b281231e947b51223ba14acf1a749", 2491 | "reference": "144c5e51266b281231e947b51223ba14acf1a749", 2492 | "shasum": "" 2493 | }, 2494 | "require": { 2495 | "php": "^7.2.5", 2496 | "psr/container": "^1.0" 2497 | }, 2498 | "suggest": { 2499 | "symfony/service-implementation": "" 2500 | }, 2501 | "type": "library", 2502 | "extra": { 2503 | "branch-alias": { 2504 | "dev-master": "2.0-dev" 2505 | } 2506 | }, 2507 | "autoload": { 2508 | "psr-4": { 2509 | "Symfony\\Contracts\\Service\\": "" 2510 | } 2511 | }, 2512 | "notification-url": "https://packagist.org/downloads/", 2513 | "license": [ 2514 | "MIT" 2515 | ], 2516 | "authors": [ 2517 | { 2518 | "name": "Nicolas Grekas", 2519 | "email": "p@tchwork.com" 2520 | }, 2521 | { 2522 | "name": "Symfony Community", 2523 | "homepage": "https://symfony.com/contributors" 2524 | } 2525 | ], 2526 | "description": "Generic abstractions related to writing services", 2527 | "homepage": "https://symfony.com", 2528 | "keywords": [ 2529 | "abstractions", 2530 | "contracts", 2531 | "decoupling", 2532 | "interfaces", 2533 | "interoperability", 2534 | "standards" 2535 | ], 2536 | "time": "2019-11-18T17:27:11+00:00" 2537 | }, 2538 | { 2539 | "name": "symfony/stopwatch", 2540 | "version": "v5.0.7", 2541 | "source": { 2542 | "type": "git", 2543 | "url": "https://github.com/symfony/stopwatch.git", 2544 | "reference": "a1d86d30d4522423afc998f32404efa34fcf5a73" 2545 | }, 2546 | "dist": { 2547 | "type": "zip", 2548 | "url": "https://api.github.com/repos/symfony/stopwatch/zipball/a1d86d30d4522423afc998f32404efa34fcf5a73", 2549 | "reference": "a1d86d30d4522423afc998f32404efa34fcf5a73", 2550 | "shasum": "" 2551 | }, 2552 | "require": { 2553 | "php": "^7.2.5", 2554 | "symfony/service-contracts": "^1.0|^2" 2555 | }, 2556 | "type": "library", 2557 | "extra": { 2558 | "branch-alias": { 2559 | "dev-master": "5.0-dev" 2560 | } 2561 | }, 2562 | "autoload": { 2563 | "psr-4": { 2564 | "Symfony\\Component\\Stopwatch\\": "" 2565 | }, 2566 | "exclude-from-classmap": [ 2567 | "/Tests/" 2568 | ] 2569 | }, 2570 | "notification-url": "https://packagist.org/downloads/", 2571 | "license": [ 2572 | "MIT" 2573 | ], 2574 | "authors": [ 2575 | { 2576 | "name": "Fabien Potencier", 2577 | "email": "fabien@symfony.com" 2578 | }, 2579 | { 2580 | "name": "Symfony Community", 2581 | "homepage": "https://symfony.com/contributors" 2582 | } 2583 | ], 2584 | "description": "Symfony Stopwatch Component", 2585 | "homepage": "https://symfony.com", 2586 | "funding": [ 2587 | { 2588 | "url": "https://symfony.com/sponsor", 2589 | "type": "custom" 2590 | }, 2591 | { 2592 | "url": "https://github.com/fabpot", 2593 | "type": "github" 2594 | }, 2595 | { 2596 | "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", 2597 | "type": "tidelift" 2598 | } 2599 | ], 2600 | "time": "2020-03-27T16:56:45+00:00" 2601 | }, 2602 | { 2603 | "name": "symfony/yaml", 2604 | "version": "v5.0.7", 2605 | "source": { 2606 | "type": "git", 2607 | "url": "https://github.com/symfony/yaml.git", 2608 | "reference": "ad5e9c83ade5bbb3a96a3f30588a0622708caefd" 2609 | }, 2610 | "dist": { 2611 | "type": "zip", 2612 | "url": "https://api.github.com/repos/symfony/yaml/zipball/ad5e9c83ade5bbb3a96a3f30588a0622708caefd", 2613 | "reference": "ad5e9c83ade5bbb3a96a3f30588a0622708caefd", 2614 | "shasum": "" 2615 | }, 2616 | "require": { 2617 | "php": "^7.2.5", 2618 | "symfony/polyfill-ctype": "~1.8" 2619 | }, 2620 | "conflict": { 2621 | "symfony/console": "<4.4" 2622 | }, 2623 | "require-dev": { 2624 | "symfony/console": "^4.4|^5.0" 2625 | }, 2626 | "suggest": { 2627 | "symfony/console": "For validating YAML files using the lint command" 2628 | }, 2629 | "type": "library", 2630 | "extra": { 2631 | "branch-alias": { 2632 | "dev-master": "5.0-dev" 2633 | } 2634 | }, 2635 | "autoload": { 2636 | "psr-4": { 2637 | "Symfony\\Component\\Yaml\\": "" 2638 | }, 2639 | "exclude-from-classmap": [ 2640 | "/Tests/" 2641 | ] 2642 | }, 2643 | "notification-url": "https://packagist.org/downloads/", 2644 | "license": [ 2645 | "MIT" 2646 | ], 2647 | "authors": [ 2648 | { 2649 | "name": "Fabien Potencier", 2650 | "email": "fabien@symfony.com" 2651 | }, 2652 | { 2653 | "name": "Symfony Community", 2654 | "homepage": "https://symfony.com/contributors" 2655 | } 2656 | ], 2657 | "description": "Symfony Yaml Component", 2658 | "homepage": "https://symfony.com", 2659 | "funding": [ 2660 | { 2661 | "url": "https://symfony.com/sponsor", 2662 | "type": "custom" 2663 | }, 2664 | { 2665 | "url": "https://github.com/fabpot", 2666 | "type": "github" 2667 | }, 2668 | { 2669 | "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", 2670 | "type": "tidelift" 2671 | } 2672 | ], 2673 | "time": "2020-03-30T11:42:42+00:00" 2674 | }, 2675 | { 2676 | "name": "theseer/tokenizer", 2677 | "version": "1.1.3", 2678 | "source": { 2679 | "type": "git", 2680 | "url": "https://github.com/theseer/tokenizer.git", 2681 | "reference": "11336f6f84e16a720dae9d8e6ed5019efa85a0f9" 2682 | }, 2683 | "dist": { 2684 | "type": "zip", 2685 | "url": "https://api.github.com/repos/theseer/tokenizer/zipball/11336f6f84e16a720dae9d8e6ed5019efa85a0f9", 2686 | "reference": "11336f6f84e16a720dae9d8e6ed5019efa85a0f9", 2687 | "shasum": "" 2688 | }, 2689 | "require": { 2690 | "ext-dom": "*", 2691 | "ext-tokenizer": "*", 2692 | "ext-xmlwriter": "*", 2693 | "php": "^7.0" 2694 | }, 2695 | "type": "library", 2696 | "autoload": { 2697 | "classmap": [ 2698 | "src/" 2699 | ] 2700 | }, 2701 | "notification-url": "https://packagist.org/downloads/", 2702 | "license": [ 2703 | "BSD-3-Clause" 2704 | ], 2705 | "authors": [ 2706 | { 2707 | "name": "Arne Blankerts", 2708 | "email": "arne@blankerts.de", 2709 | "role": "Developer" 2710 | } 2711 | ], 2712 | "description": "A small library for converting tokenized PHP source code into XML and potentially other formats", 2713 | "time": "2019-06-13T22:48:21+00:00" 2714 | }, 2715 | { 2716 | "name": "webmozart/assert", 2717 | "version": "1.8.0", 2718 | "source": { 2719 | "type": "git", 2720 | "url": "https://github.com/webmozart/assert.git", 2721 | "reference": "ab2cb0b3b559010b75981b1bdce728da3ee90ad6" 2722 | }, 2723 | "dist": { 2724 | "type": "zip", 2725 | "url": "https://api.github.com/repos/webmozart/assert/zipball/ab2cb0b3b559010b75981b1bdce728da3ee90ad6", 2726 | "reference": "ab2cb0b3b559010b75981b1bdce728da3ee90ad6", 2727 | "shasum": "" 2728 | }, 2729 | "require": { 2730 | "php": "^5.3.3 || ^7.0", 2731 | "symfony/polyfill-ctype": "^1.8" 2732 | }, 2733 | "conflict": { 2734 | "vimeo/psalm": "<3.9.1" 2735 | }, 2736 | "require-dev": { 2737 | "phpunit/phpunit": "^4.8.36 || ^7.5.13" 2738 | }, 2739 | "type": "library", 2740 | "autoload": { 2741 | "psr-4": { 2742 | "Webmozart\\Assert\\": "src/" 2743 | } 2744 | }, 2745 | "notification-url": "https://packagist.org/downloads/", 2746 | "license": [ 2747 | "MIT" 2748 | ], 2749 | "authors": [ 2750 | { 2751 | "name": "Bernhard Schussek", 2752 | "email": "bschussek@gmail.com" 2753 | } 2754 | ], 2755 | "description": "Assertions to validate method input/output with nice error messages.", 2756 | "keywords": [ 2757 | "assert", 2758 | "check", 2759 | "validate" 2760 | ], 2761 | "time": "2020-04-18T12:12:48+00:00" 2762 | } 2763 | ], 2764 | "aliases": [], 2765 | "minimum-stability": "stable", 2766 | "stability-flags": [], 2767 | "prefer-stable": false, 2768 | "prefer-lowest": false, 2769 | "platform": { 2770 | "php": ">=7.2.0" 2771 | }, 2772 | "platform-dev": [], 2773 | "plugin-api-version": "1.1.0" 2774 | } 2775 | --------------------------------------------------------------------------------