├── .gitignore ├── tests ├── samples │ ├── empty-config.json │ ├── type-test-config-required.json │ ├── syntax-sugar.json │ ├── type-test-config.json │ ├── purify-test-config.json │ └── test-config.json ├── bootstrap.php ├── AssertException.php ├── PurifierTest.php ├── BlockHandlerTest.php ├── SyntaxSugarTest.php ├── TypeTest.php └── GeneralTest.php ├── phpunit.xml ├── EditorJS ├── EditorJSException.php ├── ConfigLoader.php ├── EditorJS.php └── BlockHandler.php ├── composer.json ├── LICENSE ├── .php_cs ├── README.md └── composer.lock /.gitignore: -------------------------------------------------------------------------------- 1 | vendor/ 2 | .idea/ -------------------------------------------------------------------------------- /tests/samples/empty-config.json: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /tests/bootstrap.php: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | ./tests/ 6 | 7 | 8 | -------------------------------------------------------------------------------- /EditorJS/EditorJSException.php: -------------------------------------------------------------------------------- 1 | =5.6", 14 | "ezyang/htmlpurifier": "^4.8" 15 | }, 16 | "require-dev": { 17 | "phpunit/phpunit": "5.4.*", 18 | "friendsofphp/php-cs-fixer": "^2.13" 19 | }, 20 | "autoload": { 21 | "psr-4": {"EditorJS\\": "EditorJS"} 22 | }, 23 | "scripts": { 24 | "test": "vendor/bin/phpunit", 25 | "csfix": "vendor/bin/php-cs-fixer fix --verbose" 26 | } 27 | } -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 CodeX 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /EditorJS/ConfigLoader.php: -------------------------------------------------------------------------------- 1 | loadTools($config); 29 | } 30 | 31 | /** 32 | * Load settings for tools from configuration 33 | * 34 | * @param array $config 35 | * 36 | * @throws EditorJSException 37 | */ 38 | private function loadTools($config) 39 | { 40 | if (!isset($config['tools'])) { 41 | throw new EditorJSException('Tools not found in configuration'); 42 | } 43 | 44 | foreach ($config['tools'] as $toolName => $toolData) { 45 | if (isset($this->tools[$toolName])) { 46 | throw new EditorJSException("Duplicate tool $toolName in configuration"); 47 | } 48 | 49 | $this->tools[$toolName] = $this->loadTool($toolData); 50 | } 51 | } 52 | 53 | /** 54 | * Load settings for tool 55 | * 56 | * @param array $data 57 | * 58 | * @return array 59 | */ 60 | private function loadTool($data) 61 | { 62 | return $data; 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /tests/samples/test-config.json: -------------------------------------------------------------------------------- 1 | { 2 | "tools": { 3 | "header": { 4 | "text": { 5 | "type": "string", 6 | "allowedTags": "" 7 | }, 8 | "level": { 9 | "type": "int", 10 | "canBeOnly": [2, 3, 4] 11 | } 12 | }, 13 | "paragraph": { 14 | "text": { 15 | "type": "string", 16 | "allowedTags": "i,b,u,a[href]" 17 | } 18 | }, 19 | "list": { 20 | "style": { 21 | "type": "string", 22 | "canBeOnly": ["ordered", "unordered"] 23 | }, 24 | "items": { 25 | "type": "array", 26 | "data": { 27 | "-": { 28 | "type": "string", 29 | "allowedTags": "i,b,u" 30 | } 31 | } 32 | } 33 | }, 34 | "quote": { 35 | "text": { 36 | "type": "string", 37 | "allowedTags": "i,b,u" 38 | }, 39 | "caption": { 40 | "type": "string" 41 | }, 42 | "alignment": { 43 | "type": "string", 44 | "canBeOnly": ["left", "center"] 45 | } 46 | }, 47 | "table": { 48 | "header": { 49 | "type": "array", 50 | "data": { 51 | "description": { 52 | "type": "string" 53 | }, 54 | "author": { 55 | "type": "string" 56 | } 57 | } 58 | }, 59 | "rows": { 60 | "type": "array", 61 | "data": { 62 | "-": { 63 | "type": "array", 64 | "data": { 65 | "-": { 66 | "type": "string" 67 | } 68 | } 69 | } 70 | } 71 | } 72 | } 73 | } 74 | } -------------------------------------------------------------------------------- /.php_cs: -------------------------------------------------------------------------------- 1 | setUsingCache(false) 5 | ->setRules([ 6 | '@PSR2' => true, 7 | 'array_syntax' => ['syntax' => 'short'], 8 | 'ordered_imports' => true, 9 | 'single_import_per_statement' => false, 10 | 'no_whitespace_in_blank_line' => true, 11 | 'no_unused_imports' => true, 12 | 'no_blank_lines_before_namespace' => false, 13 | 'blank_line_before_return' => true, 14 | 'binary_operator_spaces' => true, 15 | 'cast_spaces' => true, 16 | 'short_scalar_cast' => true, 17 | 'declare_equal_normalize' => true, 18 | 'method_argument_space' => true, 19 | 'method_separation' => true, 20 | 'no_leading_namespace_whitespace' => true, 21 | 'no_multiline_whitespace_around_double_arrow' => true, 22 | 'no_whitespace_before_comma_in_array' => true, 23 | 'trim_array_spaces' => true, 24 | //'single_quote' => true, 25 | 'phpdoc_add_missing_param_annotation' => true, 26 | 'phpdoc_align' => true, 27 | 'phpdoc_scalar' => true, 28 | 'phpdoc_indent' => true, 29 | 'phpdoc_order' => true, 30 | 'phpdoc_separation' => true, 31 | 'no_empty_statement' => true, 32 | 'concat_space' => ['spacing' => 'one'], 33 | 'no_multiline_whitespace_before_semicolons' => true, 34 | 'no_leading_import_slash' => true, 35 | 'no_trailing_comma_in_list_call' => true, 36 | 'no_trailing_comma_in_singleline_array' => true, 37 | 'phpdoc_add_missing_param_annotation' => true, 38 | 'phpdoc_align' => true, 39 | 'phpdoc_no_empty_return' => true, 40 | 'return_type_declaration' => true, 41 | 'ternary_operator_spaces' => true, 42 | ]) 43 | ->setFinder( 44 | PhpCsFixer\Finder::create() 45 | ->in(__DIR__) 46 | ); -------------------------------------------------------------------------------- /tests/AssertException.php: -------------------------------------------------------------------------------- 1 | fail(sprintf('An exception of type "%s" does not exist.', $expectedException)); 11 | } 12 | 13 | try { 14 | $callback(); 15 | } catch (\Exception $e) { 16 | $class = get_class($e); 17 | $message = $e->getMessage(); 18 | $code = $e->getCode(); 19 | 20 | $errorMessage = 'Failed asserting the class of exception'; 21 | 22 | if ($message && $code) { 23 | $errorMessage .= sprintf(' (message was %s, code was %d)', $message, $code); 24 | } elseif ($code) { 25 | $errorMessage .= sprintf(' (code was %d)', $code); 26 | } 27 | 28 | $errorMessage .= '.'; 29 | $this->assertInstanceOf($expectedException, $e, $errorMessage); 30 | 31 | if ($expectedCode !== null) { 32 | $this->assertEquals($expectedCode, $code, sprintf('Failed asserting code of thrown %s.', $class)); 33 | } 34 | 35 | if ($expectedMessage !== null) { 36 | $this->assertContains($expectedMessage, $message, sprintf('Failed asserting the message of thrown %s.', $class)); 37 | } 38 | 39 | return; 40 | } 41 | 42 | $errorMessage = 'Failed asserting that exception'; 43 | 44 | if (strtolower($expectedException) !== 'exception') { 45 | $errorMessage .= sprintf(' of type %s', $expectedException); 46 | } 47 | 48 | $errorMessage .= ' was thrown.'; 49 | $this->fail($errorMessage); 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /tests/PurifierTest.php: -------------------------------------------------------------------------------- 1 | configuration = file_get_contents(PurifierTest::CONFIGURATION_FILE); 25 | } 26 | 27 | public function testHtmlPurifier() 28 | { 29 | $data = '{"time":1539180803359,"blocks":[{"type":"header","data":{"text":"test","level":2}}, {"type":"quote","data":{"text":"test","caption":"", "alignment":"left"}}]}'; 30 | $editor = new EditorJS($data, $this->configuration); 31 | $result = $editor->getBlocks(); 32 | 33 | $this->assertEquals(2, count($result)); 34 | $this->assertEquals('test', $result[0]['data']['text']); 35 | $this->assertEquals('test', $result[1]['data']['text']); 36 | } 37 | 38 | public function testCustomTagPurifier() 39 | { 40 | $data = '{"time":1539180803359,"blocks":[{"type":"header","data":{"text":"test","level":2}}]}'; 41 | $editor = new EditorJS($data, $this->configuration); 42 | $result = $editor->getBlocks(); 43 | 44 | $this->assertEquals('test', $result[0]['data']['text']); 45 | } 46 | 47 | public function testAllTagsPurifier() 48 | { 49 | $data = '{"time":1539180803359,"blocks":[{"type":"raw","data":{"html": "
Any HTML code
"}}]}'; 50 | $editor = new EditorJS($data, $this->configuration); 51 | $result = $editor->getBlocks(); 52 | 53 | $this->assertEquals('
Any HTML code
', $result[0]['data']['html']); 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /tests/BlockHandlerTest.php: -------------------------------------------------------------------------------- 1 | configuration = file_get_contents(BlockHandlerTest::CONFIGURATION_FILE); 27 | } 28 | 29 | public function testLoad() 30 | { 31 | new EditorJS(BlockHandlerTest::SAMPLE_VALID_DATA, $this->configuration); 32 | } 33 | 34 | public function testSanitizing() 35 | { 36 | $data = '{"blocks":[{"type":"header","data":{"text":"CodeX Editor", "level": 2}}]}'; 37 | 38 | $editor = new EditorJS($data, $this->configuration); 39 | $result = $editor->getBlocks(); 40 | 41 | $this->assertEquals('CodeX Editor', $result[0]['data']['text']); 42 | } 43 | 44 | public function testSanitizingAllowedTags() 45 | { 46 | $data = '{"blocks":[{"type":"paragraph","data":{"text":"CodeX Editor ifmo.su"}}]}'; 47 | 48 | $editor = new EditorJS($data, $this->configuration); 49 | $result = $editor->getBlocks(); 50 | 51 | $this->assertEquals('CodeX Editor ifmo.su', $result[0]['data']['text']); 52 | } 53 | 54 | public function testCanBeOnly() 55 | { 56 | $callable = function () { 57 | new EditorJS('{"blocks":[{"type":"header","data":{"text":"test","level":5}}]}', $this->configuration); 58 | }; 59 | 60 | $this->assertException($callable, EditorJSException::class, null, 'Option \'level\' with value `5` has invalid value. Check canBeOnly param.'); 61 | } 62 | 63 | public function testListTool() 64 | { 65 | $data = '{"time":1539180803359,"blocks":[{"type":"list","data":{"style":"ordered","items":["first","second","third"]}}],"version":"2.1.1"}'; 66 | $editor = new EditorJS($data, $this->configuration); 67 | $result = $editor->getBlocks(); 68 | 69 | $this->assertEquals(3, count($result[0]['data']['items'])); 70 | $this->assertEquals("first", $result[0]['data']['items'][0]); 71 | $this->assertEquals("second", $result[0]['data']['items'][1]); 72 | $this->assertEquals("third", $result[0]['data']['items'][2]); 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /tests/SyntaxSugarTest.php: -------------------------------------------------------------------------------- 1 | configuration = file_get_contents(SyntaxSugarTest::CONFIGURATION_FILE); 26 | } 27 | 28 | public function testShortTypeField() 29 | { 30 | $data = '{"blocks":[{"type":"header","data":{"text":"CodeX Editor", "level": 2}}]}'; 31 | 32 | $editor = new EditorJS($data, $this->configuration); 33 | $result = $editor->getBlocks(); 34 | 35 | $this->assertEquals('CodeX Editor', $result[0]['data']['text']); 36 | $this->assertEquals(2, $result[0]['data']['level']); 37 | } 38 | 39 | public function testShortTypeFieldCanBeOnly() 40 | { 41 | $callable = function () { 42 | new EditorJS('{"blocks":[{"type":"header","data":{"text":"CodeX Editor", "level": 5}}]}', 43 | $this->configuration); 44 | }; 45 | 46 | $this->assertException($callable, EditorJSException::class, null, 'Option \'level\' with value `5` has invalid value. Check canBeOnly param.'); 47 | } 48 | 49 | public function testShortIntValid() 50 | { 51 | new EditorJS('{"blocks":[{"type":"subtitle","data":{"text": "string", "level": 1337}}]}', $this->configuration); 52 | } 53 | 54 | public function testShortIntNotValid() 55 | { 56 | $callable = function () { 57 | new EditorJS('{"blocks":[{"type":"subtitle","data":{"text": "test", "level": "string"}}]}', $this->configuration); 58 | }; 59 | 60 | $this->assertException($callable, EditorJSException::class, null, 'Option \'level\' with value `string` must be integer'); 61 | } 62 | 63 | public function testInvalidType() 64 | { 65 | $callable = function () { 66 | $invalid_configuration = '{"tools": {"header": {"title": "invalid_type"}}}'; 67 | new EditorJS('{"blocks":[{"type":"header","data":{"title": "test"}}]}', $invalid_configuration); 68 | }; 69 | 70 | $this->assertException($callable, EditorJSException::class, null, 'Unhandled type `invalid_type`'); 71 | } 72 | 73 | public function testMixedStructure() 74 | { 75 | $data = '{"time":1539180803359,"blocks":[{"type":"header","data":{"text":"test","level":2}}, {"type":"quote","data":{"text":"test","caption":"", "alignment":"left"}}]}'; 76 | $editor = new EditorJS($data, $this->configuration); 77 | $result = $editor->getBlocks(); 78 | 79 | $this->assertEquals(2, count($result)); 80 | $this->assertEquals('test', $result[0]['data']['text']); 81 | $this->assertEquals('test', $result[1]['data']['text']); 82 | } 83 | } 84 | -------------------------------------------------------------------------------- /tests/TypeTest.php: -------------------------------------------------------------------------------- 1 | configuration = file_get_contents(TypeTest::CONFIGURATION_FILE); 27 | } 28 | 29 | public function testBooleanFailed() 30 | { 31 | $callable_not_bool = function () { 32 | new EditorJS('{"blocks":[{"type":"test","data":{"bool_test":"not boolean"}}]}', $this->configuration); 33 | }; 34 | 35 | $this->assertException($callable_not_bool, EditorJSException::class, null, 'Option \'bool_test\' with value `not boolean` must be boolean'); 36 | } 37 | 38 | public function testBooleanValid() 39 | { 40 | new EditorJS('{"blocks":[{"type":"test","data":{"bool_test":true}}]}', $this->configuration); 41 | } 42 | 43 | public function testIntegerValid() 44 | { 45 | new EditorJS('{"blocks":[{"type":"test","data":{"int_test": 5}}]}', $this->configuration); 46 | } 47 | 48 | public function testIntegerFailed() 49 | { 50 | $callable = function () { 51 | new EditorJS('{"blocks":[{"type":"test","data":{"int_test": "not integer"}}]}', $this->configuration); 52 | }; 53 | 54 | $this->assertException($callable, EditorJSException::class, null, 'Option \'int_test\' with value `not integer` must be integer'); 55 | } 56 | 57 | public function testStringValid() 58 | { 59 | new EditorJS('{"blocks":[{"type":"test","data":{"string_test": "string"}}]}', $this->configuration); 60 | } 61 | 62 | public function testStringFailed() 63 | { 64 | $callable = function () { 65 | new EditorJS('{"blocks":[{"type":"test","data":{"string_test": 17}}]}', $this->configuration); 66 | }; 67 | 68 | $this->assertException($callable, EditorJSException::class, null, 'Option \'string_test\' with value `17` must be string'); 69 | } 70 | 71 | public function testAllowedNullNotRequired() 72 | { 73 | new EditorJS('{"blocks":[{"type":"test","data":{"int_test": null}}]}', $this->configuration); 74 | } 75 | 76 | public function testDisallowedNullNotRequired() 77 | { 78 | $callable = function () { 79 | new EditorJS('{"blocks":[{"type":"test","data":{"string_test": null}}]}', $this->configuration); 80 | }; 81 | 82 | $this->assertException($callable, EditorJSException::class, null, 'string_test\' with value `` must be string'); 83 | } 84 | 85 | public function testNullRequired() 86 | { 87 | new EditorJS('{"blocks":[{"type":"test","data":{"string_test": "qwe"}}]}', file_get_contents(TypeTest::CONFIGURATION_FILE_REQUIRED)); 88 | 89 | $callable = function () { 90 | new EditorJS('{"blocks":[{"type":"test","data":{"string_test": null}}]}', file_get_contents(TypeTest::CONFIGURATION_FILE_REQUIRED)); 91 | }; 92 | $this->assertException($callable, EditorJSException::class, null, 'Not found required param `string_test`'); 93 | } 94 | } 95 | -------------------------------------------------------------------------------- /EditorJS/EditorJS.php: -------------------------------------------------------------------------------- 1 | handler = new BlockHandler($configuration); 39 | 40 | /** 41 | * Check if json string is empty 42 | */ 43 | if (empty($json)) { 44 | throw new EditorJSException('JSON is empty'); 45 | } 46 | 47 | /** 48 | * Check input data 49 | */ 50 | $data = json_decode($json, true); 51 | 52 | /** 53 | * Handle decoding JSON error 54 | */ 55 | if (json_last_error()) { 56 | throw new EditorJSException('Wrong JSON format: ' . json_last_error_msg()); 57 | } 58 | 59 | /** 60 | * Check if data is null 61 | */ 62 | if (is_null($data)) { 63 | throw new EditorJSException('Input is null'); 64 | } 65 | 66 | /** 67 | * Count elements in data array 68 | */ 69 | if (count($data) === 0) { 70 | throw new EditorJSException('Input array is empty'); 71 | } 72 | 73 | /** 74 | * Check if blocks param is missing in data 75 | */ 76 | if (!isset($data['blocks'])) { 77 | throw new EditorJSException('Field `blocks` is missing'); 78 | } 79 | 80 | 81 | if (!is_array($data['blocks'])) { 82 | throw new EditorJSException('Blocks is not an array'); 83 | } 84 | 85 | foreach ($data['blocks'] as $blockData) { 86 | if (is_array($blockData)) { 87 | array_push($this->blocks, $blockData); 88 | } else { 89 | throw new EditorJSException('Block must be an Array'); 90 | } 91 | } 92 | 93 | /** 94 | * Validate blocks structure 95 | */ 96 | $this->validateBlocks(); 97 | } 98 | 99 | /** 100 | * Sanitize and return array of blocks according to the Handler's rules. 101 | * 102 | * @return array 103 | */ 104 | public function getBlocks() 105 | { 106 | $sanitizedBlocks = []; 107 | 108 | foreach ($this->blocks as $block) { 109 | $sanitizedBlock = $this->handler->sanitizeBlock( 110 | $block['type'], 111 | $block['data'], 112 | $block["tunes"] ?? [] 113 | ); 114 | if (!empty($sanitizedBlock)) { 115 | array_push($sanitizedBlocks, $sanitizedBlock); 116 | } 117 | } 118 | 119 | return $sanitizedBlocks; 120 | } 121 | 122 | /** 123 | * Validate blocks structure according to the Handler's rules. 124 | * 125 | * @return bool 126 | */ 127 | private function validateBlocks() 128 | { 129 | foreach ($this->blocks as $block) { 130 | if (!$this->handler->validateBlock($block['type'], $block['data'])) { 131 | return false; 132 | } 133 | } 134 | 135 | return true; 136 | } 137 | } 138 | -------------------------------------------------------------------------------- /tests/GeneralTest.php: -------------------------------------------------------------------------------- 1 | config = file_get_contents(GeneralTest::CONFIGURATION_FILE); 25 | } 26 | 27 | public function testValidData() 28 | { 29 | new EditorJS(GeneralTest::SAMPLE_VALID_DATA, $this->config); 30 | } 31 | 32 | public function testNullInput() 33 | { 34 | $callable = function () { 35 | new EditorJS('', $this->config); 36 | }; 37 | 38 | $this->assertException($callable, EditorJSException::class, null, 'JSON is empty'); 39 | } 40 | 41 | public function testEmptyArray() 42 | { 43 | $callable = function () { 44 | new EditorJS('{}', $this->config); 45 | }; 46 | 47 | $this->assertException($callable, EditorJSException::class, null, 'Input array is empty'); 48 | } 49 | 50 | public function testWrongJson() 51 | { 52 | $callable = function () { 53 | new EditorJS('{[{', $this->config); 54 | }; 55 | 56 | $this->assertException($callable, EditorJSException::class, null, 'Wrong JSON format: Syntax error'); 57 | } 58 | 59 | public function testValidConfig() 60 | { 61 | new ConfigLoader(file_get_contents(TESTS_DIR . "/samples/test-config.json")); 62 | } 63 | 64 | public function testItemsMissed() 65 | { 66 | $callable = function () { 67 | new EditorJS('{"s":""}', $this->config); 68 | }; 69 | 70 | $this->assertException($callable, EditorJSException::class, null, 'Field `blocks` is missing'); 71 | } 72 | 73 | public function testUnicode() 74 | { 75 | $callable = function () { 76 | new EditorJS('{"s":"😀"}', $this->config); 77 | }; 78 | 79 | $this->assertException($callable, EditorJSException::class, null, 'Field `blocks` is missing'); 80 | } 81 | 82 | public function testInvalidBlock() 83 | { 84 | $callable = function () { 85 | new EditorJS('{"blocks":""}', $this->config); 86 | }; 87 | 88 | $this->assertException($callable, EditorJSException::class, null, 'Blocks is not an array'); 89 | } 90 | 91 | public function testBlocksContent() 92 | { 93 | $callable = function () { 94 | new EditorJS('{"blocks":["",""]}', $this->config); 95 | }; 96 | 97 | $this->assertException($callable, EditorJSException::class, null, 'Block must be an Array'); 98 | } 99 | 100 | public function testNested() 101 | { 102 | $data = '{"blocks":[{"type":"table","data":{"header": {"description":"a table", "author": "codex"}, "rows": [["name", "age", "sex"],["Paul", "24", "male"],["Ann", "26", "female"]]}}]}'; 103 | $editor = new EditorJS($data, $this->config); 104 | $result = $editor->getBlocks(); 105 | 106 | $valid_rows = [["name", "age", "sex"],["Paul", "24", "male"],["Ann", "26", "female"]]; 107 | 108 | $this->assertEquals('a table', $result[0]['data']['header']['description']); 109 | $this->assertEquals('codex', $result[0]['data']['header']['author']); 110 | $this->assertEquals(3, count($result[0]['data']['rows'])); 111 | 112 | $this->assertEquals('name', $result[0]['data']['rows'][0][0]); 113 | $this->assertEquals('24', $result[0]['data']['rows'][1][1]); 114 | $this->assertEquals('female', $result[0]['data']['rows'][2][2]); 115 | } 116 | } 117 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Editor.js PHP 2 | 3 | Server-side implementation sample for the Editor.js. It contains data validation, HTML sanitization and converts output from Editor.js to the Block objects. 4 | 5 | # Installation 6 | 7 | To install lib use composer: 8 | ``` 9 | composer require codex-team/editor.js:dev-master 10 | ``` 11 | 12 | # Guide 13 | 14 | Add this line at the top of your PHP script 15 | 16 | ```php 17 | use \EditorJS\EditorJS; 18 | ``` 19 | 20 | this line allows you to get editors class that has the following method: 21 | 22 | `getBlocks` - return array of sanitized blocks 23 | 24 | # Basic usage 25 | 26 | You can get data from editor and send as param to editor's server validator like 27 | 28 | ```php 29 | try { 30 | // Initialize Editor backend and validate structure 31 | $editor = new EditorJS( $data, $configuration ); 32 | 33 | // Get sanitized blocks (according to the rules from configuration) 34 | $blocks = $editor->getBlocks(); 35 | 36 | } catch (\EditorJSException $e) { 37 | // process exception 38 | } 39 | ``` 40 | 41 | Editor.js constructor has the following arguments: 42 | 43 | `$data` — JSON string with data from CodeX Editor frontend. 44 | 45 | `$configuration` — JSON string with CodeX Editor tools configuration (see an example in the following paragraph). 46 | 47 | # Configuration file 48 | 49 | You can manually configure validation rules for different types of Editor.js tools (header, paragraph, list, quote and other). 50 | You can also extend configuration with new tools. 51 | 52 | Sample validation rule set: 53 | 54 | ```$json 55 | { 56 | "tools": { 57 | "header": { 58 | "text": { 59 | "type": "string", 60 | "required": true, 61 | "allowedTags": "b,i,a[href]" 62 | }, 63 | "level": { 64 | "type": "int", 65 | "canBeOnly": [2, 3, 4] 66 | } 67 | } 68 | } 69 | } 70 | ``` 71 | 72 | Where: 73 | 74 | `tools` — array of supported Editor.js tools. 75 | 76 | `header` — defines `header` tool settings. 77 | 78 | `text` and `level` — parameters in `header` tool structure. 79 | 80 | `text` is a **required** *string*, which will be sanitized except *b*, *i* and *a[href]* tags. 81 | 82 | `level` is an **optional** *integer* that can be only 0, 1 or 2. 83 | 84 | `allowedTags` param should follow [HTMLPurifier](https://github.com/ezyang/htmlpurifier) format. 85 | 86 | #### There are three common parameters for every block: 87 | 88 | 1. `type` (**required**) — type of the block 89 | 90 | |value|description| 91 | |---|---| 92 | |`string`|field with string value| 93 | |`int`/`integer`|field with integer value| 94 | |`bool`/`boolean`|field with boolean value| 95 | |`array`|field with nested fields| 96 | 97 | 2. `allowedTags` (optional) — HTML tags in string that won't be removed 98 | 99 | |value|default|description| 100 | |---|---|---| 101 | |`empty`|yes|all tags will be removed| 102 | |`*`|no|all tags are allowed| 103 | 104 | Other values are allowed according to the [HTMLPurifier](https://github.com/ezyang/htmlpurifier) format. 105 | 106 | Example: 107 | ``` 108 | "paragraph": { 109 | "text": { 110 | "type": "string", 111 | "allowedTags": "i,b,u,a[href]" 112 | } 113 | } 114 | ``` 115 | 116 | 3. `canBeOnly` (optional) — define set of allowed values 117 | 118 | Example: 119 | ``` 120 | "quote": { 121 | "text": { 122 | "type": "string" 123 | }, 124 | "caption": { 125 | "type": "string" 126 | }, 127 | "alignment": { 128 | "type": "string", 129 | "canBeOnly": ["left", "center"] 130 | } 131 | } 132 | ``` 133 | 134 | ### Short settings syntax 135 | 136 | Some syntax sugar has been added. 137 | 138 | Tool settings can be a `string`. It defines tool's type with default settings. 139 | ```json 140 | "header": { 141 | "text": "string", 142 | "level": "int" 143 | } 144 | ``` 145 | 146 | It evaluates to: 147 | ```json 148 | "header": { 149 | "text": { 150 | "type": "string", 151 | "allowedTags": "", 152 | "required": true 153 | }, 154 | "level": { 155 | "type": "int", 156 | "allowedTags": "", 157 | "required": true 158 | } 159 | } 160 | ``` 161 | 162 | Tool settings can be an `array`. It defines a set of allowed values without sanitizing. 163 | ```json 164 | "quote": { 165 | "alignment": ["left", "center"], 166 | "caption": "string" 167 | } 168 | ``` 169 | 170 | It evaluates to: 171 | ```json 172 | "quote": { 173 | "alignment": { 174 | "type": "string", 175 | "canBeOnly": ["left", "center"] 176 | }, 177 | "caption": { 178 | "type": "string", 179 | "allowedTags": "", 180 | "required": true 181 | } 182 | } 183 | ``` 184 | 185 | Another configuration example: [/tests/samples/syntax-sugar.json](/tests/samples/syntax-sugar.json) 186 | 187 | ### Nested tools 188 | 189 | Tools can contain nested values. It is possible with the `array` type. 190 | 191 | Let the JSON input be the following: 192 | ``` 193 | { 194 | "blocks": [ 195 | "type": list, 196 | "data": { 197 | "items": [ 198 | "first", "second", "third" 199 | ], 200 | "style": { 201 | "background-color": "red", 202 | "font-color": "black" 203 | } 204 | } 205 | ] 206 | } 207 | ``` 208 | 209 | We can define validation rules for this input in the config: 210 | ``` 211 | "list": { 212 | "items": { 213 | "type": "array", 214 | "data": { 215 | "-": { 216 | "type": "string", 217 | "allowedTags": "i,b,u" 218 | } 219 | } 220 | }, 221 | "style": { 222 | "type": "array", 223 | "data": { 224 | "background-color": { 225 | "type": "string", 226 | "canBeOnly": ["red", "blue", "green"] 227 | }, 228 | "font-color": { 229 | "type": "string", 230 | "canBeOnly": ["black", "white"] 231 | } 232 | } 233 | } 234 | } 235 | ``` 236 | 237 | where `data` is the container for values of the array and `-` is the special shortcut for values if the array is sequential. 238 | 239 | 240 | 241 | Another configuration example: [/tests/samples/test-config.json](/tests/samples/test-config.json) 242 | 243 | # Exceptions 244 | 245 | ### EditorJS class 246 | | Exception text | Cause 247 | | ----------------------------- | ------------------------------------------------ 248 | | JSON is empty | EditorJS initiated with empty `$json` argument 249 | | Wrong JSON format: `error` | `json_decode` failed during `$json` processing 250 | | Input is null | `json_decode` returned null `$data` object 251 | | Input array is empty | `$data` is an empty array 252 | | Field \`blocks\` is missing | `$data` doesn't contain 'blocks' key 253 | | Blocks is not an array | `$data['blocks']` is not an array 254 | | Block must be an Array | one element in `$data['blocks']` is not an array 255 | 256 | ### BlockHandler class 257 | | Exception text | Cause 258 | | --------------------- | ----------------------------------------------- 259 | | Tool \`**TOOL_NAME**\` not found in the configuration | Configuration file doesn't contain **TOOL_NAME** in `tools{}` dictionary 260 | | Not found required param \`**key**\` | **key** tool param exists in configuration but doesn't exist in input data. *(Params are always required by default unless `required: false` is set)* 261 | | Found extra param \`**key**\` | Param **key** exists in input data but doesn't defined in configuration 262 | | Option \`**key**\` with value \`**value**\` has invalid value. Check canBeOnly param. | Parameter must have one of the values from **canBeOnly** array in tool configuration 263 | | Option \`**key**\` with value \`**value**\` must be **TYPE** | Param must have type which is defined in tool configuration *(string, integer, boolean)* 264 | | Unhandled type \`**elementType**\` | Param type in configuration is invalid 265 | 266 | ### ConfigLoader class 267 | | Exception text | Cause 268 | | ----------------------------- | ------------------------------------------------ 269 | | Configuration data is empty | EditorJS initiated with empty `$configuration` argument 270 | | Tools not found in configuration | Configuration file doesn't contain `tools` key 271 | | Duplicate tool \`**toolName**\` in configuration | Configuration file has different tools with the same name 272 | 273 | # Make Tools 274 | 275 | If you connect a new Tool on the frontend-side, then you should create a configuration rule for that Tool to validate it on server-side. 276 | 277 | ## Repository 278 | https://github.com/codex-editor/editorjs-php/ 279 | 280 | 281 | ## About CodeX 282 | We are small team of Web-developing fans consisting of IFMO students and graduates located in St. Petersburg, Russia. 283 | Feel free to give us a feedback on team@ifmo.su 284 | -------------------------------------------------------------------------------- /EditorJS/BlockHandler.php: -------------------------------------------------------------------------------- 1 | rules = new ConfigLoader($configuration); 32 | } 33 | 34 | /** 35 | * Validate block for correctness 36 | * 37 | * @param string $blockType 38 | * @param array $blockData 39 | * 40 | * @throws EditorJSException 41 | * 42 | * @return bool 43 | */ 44 | public function validateBlock($blockType, $blockData) 45 | { 46 | /** 47 | * Default action for blocks that are not mentioned in a configuration 48 | */ 49 | if (!array_key_exists($blockType, $this->rules->tools)) { 50 | throw new EditorJSException("Tool `$blockType` not found in the configuration"); 51 | } 52 | 53 | $rule = $this->rules->tools[$blockType]; 54 | 55 | return $this->validate($rule, $blockData); 56 | } 57 | 58 | /** 59 | * Apply sanitizing rules according to the block type 60 | * 61 | * @param string $blockType 62 | * @param array $blockData 63 | * 64 | * @throws EditorJSException 65 | * 66 | * @return array|bool 67 | */ 68 | public function sanitizeBlock($blockType, $blockData, $blockTunes) 69 | { 70 | $rule = $this->rules->tools[$blockType]; 71 | 72 | return [ 73 | 'type' => $blockType, 74 | 'data' => $this->sanitize($rule, $blockData), 75 | 'tunes' => $blockTunes 76 | ]; 77 | } 78 | 79 | /** 80 | * Apply validation rule to the data block 81 | * 82 | * @param array $rules 83 | * @param array $blockData 84 | * 85 | * @throws EditorJSException 86 | * 87 | * @return bool 88 | */ 89 | private function validate($rules, $blockData) 90 | { 91 | /** 92 | * Make sure that every required param exists in data block 93 | */ 94 | foreach ($rules as $key => $value) { 95 | if (($key != BlockHandler::DEFAULT_ARRAY_KEY) && (isset($value['required']) ? $value['required'] : true)) { 96 | if (!isset($blockData[$key])) { 97 | throw new EditorJSException("Not found required param `$key`"); 98 | } 99 | } 100 | } 101 | 102 | /** 103 | * Check if there is not extra params (not mentioned in configuration rule) 104 | */ 105 | foreach ($blockData as $key => $value) { 106 | if (!is_integer($key) && !isset($rules[$key])) { 107 | throw new EditorJSException("Found extra param `$key`"); 108 | } 109 | } 110 | 111 | /** 112 | * Validate every key in data block 113 | */ 114 | foreach ($blockData as $key => $value) { 115 | /** 116 | * PHP Array has integer keys 117 | */ 118 | if (is_integer($key)) { 119 | $key = BlockHandler::DEFAULT_ARRAY_KEY; 120 | } 121 | 122 | $rule = $rules[$key]; 123 | 124 | $rule = $this->expandToolSettings($rule); 125 | 126 | $elementType = $rule['type']; 127 | 128 | /** 129 | * Process canBeOnly rule 130 | */ 131 | if (isset($rule['canBeOnly'])) { 132 | if (!in_array($value, $rule['canBeOnly'])) { 133 | throw new EditorJSException("Option '$key' with value `$value` has invalid value. Check canBeOnly param."); 134 | } 135 | 136 | // Do not perform additional elements validation in any case 137 | continue; 138 | } 139 | 140 | /** 141 | * Do not check element type if it is not required and null 142 | */ 143 | if (isset($rule['required']) && $rule['required'] === false && 144 | isset($rule['allow_null']) && $rule['allow_null'] === true && $value === null) { 145 | continue; 146 | } 147 | 148 | /** 149 | * Validate element types 150 | */ 151 | switch ($elementType) { 152 | case 'string': 153 | if (!is_string($value)) { 154 | throw new EditorJSException("Option '$key' with value `$value` must be string"); 155 | } 156 | break; 157 | 158 | case 'integer': 159 | case 'int': 160 | if (!is_integer($value)) { 161 | throw new EditorJSException("Option '$key' with value `$value` must be integer"); 162 | } 163 | break; 164 | 165 | case 'array': 166 | $this->validate($rule['data'], $value); 167 | break; 168 | 169 | case 'boolean': 170 | case 'bool': 171 | if (!is_bool($value)) { 172 | throw new EditorJSException("Option '$key' with value `$value` must be boolean"); 173 | } 174 | break; 175 | 176 | default: 177 | throw new EditorJSException("Unhandled type `$elementType`"); 178 | } 179 | } 180 | 181 | return true; 182 | } 183 | 184 | /** 185 | * Sanitize strings in the data block 186 | * 187 | * @param array $rules 188 | * @param array $blockData 189 | * 190 | * @throws EditorJSException 191 | * 192 | * @return array 193 | */ 194 | private function sanitize($rules, $blockData) 195 | { 196 | /** 197 | * Sanitize every key in data block 198 | */ 199 | foreach ($blockData as $key => $value) { 200 | /** 201 | * PHP Array has integer keys 202 | */ 203 | if (is_integer($key)) { 204 | $rule = $rules[BlockHandler::DEFAULT_ARRAY_KEY]; 205 | } else { 206 | $rule = $rules[$key]; 207 | } 208 | 209 | $rule = $this->expandToolSettings($rule); 210 | $elementType = $rule['type']; 211 | 212 | /** 213 | * Sanitize string with Purifier 214 | */ 215 | if ($elementType == 'string') { 216 | $allowedTags = isset($rule['allowedTags']) ? $rule['allowedTags'] : ''; 217 | if ($allowedTags !== '*') { 218 | $blockData[$key] = $this->getPurifier($allowedTags)->purify($value); 219 | } 220 | } 221 | 222 | /** 223 | * Sanitize nested elements 224 | */ 225 | if ($elementType == 'array') { 226 | $blockData[$key] = $this->sanitize($rule['data'], $value); 227 | } 228 | } 229 | 230 | return $blockData; 231 | } 232 | 233 | /** 234 | * Create and return new default purifier 235 | * 236 | * @param $allowedTags 237 | * 238 | * @return \HTMLPurifier 239 | */ 240 | private function getPurifier($allowedTags) 241 | { 242 | $sanitizer = $this->getDefaultPurifier(); 243 | 244 | $sanitizer->set('HTML.Allowed', $allowedTags); 245 | 246 | /** 247 | * Define custom HTML Definition for mark tool 248 | */ 249 | if ($def = $sanitizer->maybeGetRawHTMLDefinition()) { 250 | $def->addElement('mark', 'Inline', 'Inline', 'Common'); 251 | } 252 | 253 | $purifier = new \HTMLPurifier($sanitizer); 254 | 255 | return $purifier; 256 | } 257 | 258 | /** 259 | * Initialize HTML Purifier with default settings 260 | */ 261 | private function getDefaultPurifier() 262 | { 263 | $sanitizer = \HTMLPurifier_Config::createDefault(); 264 | 265 | $sanitizer->set('HTML.TargetBlank', true); 266 | $sanitizer->set('URI.AllowedSchemes', ['http' => true, 'https' => true, 'mailto' => true, 'tel' => true]); 267 | $sanitizer->set('AutoFormat.RemoveEmpty', true); 268 | $sanitizer->set('HTML.DefinitionID', 'html5-definitions'); 269 | 270 | $cacheDirectory = sys_get_temp_dir() . DIRECTORY_SEPARATOR . 'purifier'; 271 | if (!is_dir($cacheDirectory)) { 272 | mkdir($cacheDirectory, 0777, true); 273 | } 274 | 275 | $sanitizer->set('Cache.SerializerPath', $cacheDirectory); 276 | 277 | return $sanitizer; 278 | } 279 | 280 | /** 281 | * Check whether the array is associative or sequential 282 | * 283 | * @param array $arr – array to check 284 | * 285 | * @return bool – true if the array is associative 286 | */ 287 | private function isAssoc(array $arr) 288 | { 289 | if ([] === $arr) { 290 | return false; 291 | } 292 | 293 | return array_keys($arr) !== range(0, count($arr) - 1); 294 | } 295 | 296 | /** 297 | * Expand shortified tool settings 298 | * 299 | * @param $rule – tool settings 300 | * 301 | * @throws EditorJSException 302 | * 303 | * @return array – expanded tool settings 304 | */ 305 | private function expandToolSettings($rule) 306 | { 307 | if (is_string($rule)) { 308 | // 'blockName': 'string' – tool with string type and default settings 309 | $expandedRule = ["type" => $rule]; 310 | } elseif (is_array($rule)) { 311 | if ($this->isAssoc($rule)) { 312 | $expandedRule = $rule; 313 | } else { 314 | // 'blockName': [] – tool with canBeOnly and default settings 315 | $expandedRule = ["type" => "string", "canBeOnly" => $rule]; 316 | } 317 | } else { 318 | throw new EditorJSException("Cannot determine element type of the rule `$rule`."); 319 | } 320 | 321 | return $expandedRule; 322 | } 323 | } 324 | -------------------------------------------------------------------------------- /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": "2eb347c8d65d735df718d73b72cfd2fa", 8 | "packages": [ 9 | { 10 | "name": "composer/semver", 11 | "version": "1.4.2", 12 | "source": { 13 | "type": "git", 14 | "url": "https://github.com/composer/semver.git", 15 | "reference": "c7cb9a2095a074d131b65a8a0cd294479d785573" 16 | }, 17 | "dist": { 18 | "type": "zip", 19 | "url": "https://api.github.com/repos/composer/semver/zipball/c7cb9a2095a074d131b65a8a0cd294479d785573", 20 | "reference": "c7cb9a2095a074d131b65a8a0cd294479d785573", 21 | "shasum": "" 22 | }, 23 | "require": { 24 | "php": "^5.3.2 || ^7.0" 25 | }, 26 | "require-dev": { 27 | "phpunit/phpunit": "^4.5 || ^5.0.5", 28 | "phpunit/phpunit-mock-objects": "2.3.0 || ^3.0" 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": "2016-08-30T16:08:34+00:00" 70 | }, 71 | { 72 | "name": "composer/xdebug-handler", 73 | "version": "1.3.0", 74 | "source": { 75 | "type": "git", 76 | "url": "https://github.com/composer/xdebug-handler.git", 77 | "reference": "b8e9745fb9b06ea6664d8872c4505fb16df4611c" 78 | }, 79 | "dist": { 80 | "type": "zip", 81 | "url": "https://api.github.com/repos/composer/xdebug-handler/zipball/b8e9745fb9b06ea6664d8872c4505fb16df4611c", 82 | "reference": "b8e9745fb9b06ea6664d8872c4505fb16df4611c", 83 | "shasum": "" 84 | }, 85 | "require": { 86 | "php": "^5.3.2 || ^7.0", 87 | "psr/log": "^1.0" 88 | }, 89 | "require-dev": { 90 | "phpunit/phpunit": "^4.8.35 || ^5.7 || ^6.5" 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 | "time": "2018-08-31T19:07:57+00:00" 114 | }, 115 | { 116 | "name": "doctrine/annotations", 117 | "version": "v1.4.0", 118 | "source": { 119 | "type": "git", 120 | "url": "https://github.com/doctrine/annotations.git", 121 | "reference": "54cacc9b81758b14e3ce750f205a393d52339e97" 122 | }, 123 | "dist": { 124 | "type": "zip", 125 | "url": "https://api.github.com/repos/doctrine/annotations/zipball/54cacc9b81758b14e3ce750f205a393d52339e97", 126 | "reference": "54cacc9b81758b14e3ce750f205a393d52339e97", 127 | "shasum": "" 128 | }, 129 | "require": { 130 | "doctrine/lexer": "1.*", 131 | "php": "^5.6 || ^7.0" 132 | }, 133 | "require-dev": { 134 | "doctrine/cache": "1.*", 135 | "phpunit/phpunit": "^5.7" 136 | }, 137 | "type": "library", 138 | "extra": { 139 | "branch-alias": { 140 | "dev-master": "1.4.x-dev" 141 | } 142 | }, 143 | "autoload": { 144 | "psr-4": { 145 | "Doctrine\\Common\\Annotations\\": "lib/Doctrine/Common/Annotations" 146 | } 147 | }, 148 | "notification-url": "https://packagist.org/downloads/", 149 | "license": [ 150 | "MIT" 151 | ], 152 | "authors": [ 153 | { 154 | "name": "Roman Borschel", 155 | "email": "roman@code-factory.org" 156 | }, 157 | { 158 | "name": "Benjamin Eberlei", 159 | "email": "kontakt@beberlei.de" 160 | }, 161 | { 162 | "name": "Guilherme Blanco", 163 | "email": "guilhermeblanco@gmail.com" 164 | }, 165 | { 166 | "name": "Jonathan Wage", 167 | "email": "jonwage@gmail.com" 168 | }, 169 | { 170 | "name": "Johannes Schmitt", 171 | "email": "schmittjoh@gmail.com" 172 | } 173 | ], 174 | "description": "Docblock Annotations Parser", 175 | "homepage": "http://www.doctrine-project.org", 176 | "keywords": [ 177 | "annotations", 178 | "docblock", 179 | "parser" 180 | ], 181 | "time": "2017-02-24T16:22:25+00:00" 182 | }, 183 | { 184 | "name": "doctrine/lexer", 185 | "version": "v1.0.1", 186 | "source": { 187 | "type": "git", 188 | "url": "https://github.com/doctrine/lexer.git", 189 | "reference": "83893c552fd2045dd78aef794c31e694c37c0b8c" 190 | }, 191 | "dist": { 192 | "type": "zip", 193 | "url": "https://api.github.com/repos/doctrine/lexer/zipball/83893c552fd2045dd78aef794c31e694c37c0b8c", 194 | "reference": "83893c552fd2045dd78aef794c31e694c37c0b8c", 195 | "shasum": "" 196 | }, 197 | "require": { 198 | "php": ">=5.3.2" 199 | }, 200 | "type": "library", 201 | "extra": { 202 | "branch-alias": { 203 | "dev-master": "1.0.x-dev" 204 | } 205 | }, 206 | "autoload": { 207 | "psr-0": { 208 | "Doctrine\\Common\\Lexer\\": "lib/" 209 | } 210 | }, 211 | "notification-url": "https://packagist.org/downloads/", 212 | "license": [ 213 | "MIT" 214 | ], 215 | "authors": [ 216 | { 217 | "name": "Roman Borschel", 218 | "email": "roman@code-factory.org" 219 | }, 220 | { 221 | "name": "Guilherme Blanco", 222 | "email": "guilhermeblanco@gmail.com" 223 | }, 224 | { 225 | "name": "Johannes Schmitt", 226 | "email": "schmittjoh@gmail.com" 227 | } 228 | ], 229 | "description": "Base library for a lexer that can be used in Top-Down, Recursive Descent Parsers.", 230 | "homepage": "http://www.doctrine-project.org", 231 | "keywords": [ 232 | "lexer", 233 | "parser" 234 | ], 235 | "time": "2014-09-09T13:34:57+00:00" 236 | }, 237 | { 238 | "name": "ezyang/htmlpurifier", 239 | "version": "v4.10.0", 240 | "source": { 241 | "type": "git", 242 | "url": "https://github.com/ezyang/htmlpurifier.git", 243 | "reference": "d85d39da4576a6934b72480be6978fb10c860021" 244 | }, 245 | "dist": { 246 | "type": "zip", 247 | "url": "https://api.github.com/repos/ezyang/htmlpurifier/zipball/d85d39da4576a6934b72480be6978fb10c860021", 248 | "reference": "d85d39da4576a6934b72480be6978fb10c860021", 249 | "shasum": "" 250 | }, 251 | "require": { 252 | "php": ">=5.2" 253 | }, 254 | "require-dev": { 255 | "simpletest/simpletest": "^1.1" 256 | }, 257 | "type": "library", 258 | "autoload": { 259 | "psr-0": { 260 | "HTMLPurifier": "library/" 261 | }, 262 | "files": [ 263 | "library/HTMLPurifier.composer.php" 264 | ] 265 | }, 266 | "notification-url": "https://packagist.org/downloads/", 267 | "license": [ 268 | "LGPL" 269 | ], 270 | "authors": [ 271 | { 272 | "name": "Edward Z. Yang", 273 | "email": "admin@htmlpurifier.org", 274 | "homepage": "http://ezyang.com" 275 | } 276 | ], 277 | "description": "Standards compliant HTML filter written in PHP", 278 | "homepage": "http://htmlpurifier.org/", 279 | "keywords": [ 280 | "html" 281 | ], 282 | "time": "2018-02-23T01:58:20+00:00" 283 | }, 284 | { 285 | "name": "friendsofphp/php-cs-fixer", 286 | "version": "v2.13.0", 287 | "source": { 288 | "type": "git", 289 | "url": "https://github.com/FriendsOfPHP/PHP-CS-Fixer.git", 290 | "reference": "7136aa4e0c5f912e8af82383775460d906168a10" 291 | }, 292 | "dist": { 293 | "type": "zip", 294 | "url": "https://api.github.com/repos/FriendsOfPHP/PHP-CS-Fixer/zipball/7136aa4e0c5f912e8af82383775460d906168a10", 295 | "reference": "7136aa4e0c5f912e8af82383775460d906168a10", 296 | "shasum": "" 297 | }, 298 | "require": { 299 | "composer/semver": "^1.4", 300 | "composer/xdebug-handler": "^1.2", 301 | "doctrine/annotations": "^1.2", 302 | "ext-json": "*", 303 | "ext-tokenizer": "*", 304 | "php": "^5.6 || >=7.0 <7.3", 305 | "php-cs-fixer/diff": "^1.3", 306 | "symfony/console": "^3.2 || ^4.0", 307 | "symfony/event-dispatcher": "^3.0 || ^4.0", 308 | "symfony/filesystem": "^3.0 || ^4.0", 309 | "symfony/finder": "^3.0 || ^4.0", 310 | "symfony/options-resolver": "^3.0 || ^4.0", 311 | "symfony/polyfill-php70": "^1.0", 312 | "symfony/polyfill-php72": "^1.4", 313 | "symfony/process": "^3.0 || ^4.0", 314 | "symfony/stopwatch": "^3.0 || ^4.0" 315 | }, 316 | "conflict": { 317 | "hhvm": "*" 318 | }, 319 | "require-dev": { 320 | "johnkary/phpunit-speedtrap": "^1.1 || ^2.0 || ^3.0", 321 | "justinrainbow/json-schema": "^5.0", 322 | "keradus/cli-executor": "^1.1", 323 | "mikey179/vfsstream": "^1.6", 324 | "php-coveralls/php-coveralls": "^2.1", 325 | "php-cs-fixer/accessible-object": "^1.0", 326 | "php-cs-fixer/phpunit-constraint-isidenticalstring": "^1.0.1", 327 | "php-cs-fixer/phpunit-constraint-xmlmatchesxsd": "^1.0.1", 328 | "phpunit/phpunit": "^5.7.27 || ^6.5.8 || ^7.1", 329 | "phpunitgoodpractices/traits": "^1.5.1", 330 | "symfony/phpunit-bridge": "^4.0" 331 | }, 332 | "suggest": { 333 | "ext-mbstring": "For handling non-UTF8 characters in cache signature.", 334 | "php-cs-fixer/phpunit-constraint-isidenticalstring": "For IsIdenticalString constraint.", 335 | "php-cs-fixer/phpunit-constraint-xmlmatchesxsd": "For XmlMatchesXsd constraint.", 336 | "symfony/polyfill-mbstring": "When enabling `ext-mbstring` is not possible." 337 | }, 338 | "bin": [ 339 | "php-cs-fixer" 340 | ], 341 | "type": "application", 342 | "extra": { 343 | "branch-alias": { 344 | "dev-master": "2.13-dev" 345 | } 346 | }, 347 | "autoload": { 348 | "psr-4": { 349 | "PhpCsFixer\\": "src/" 350 | }, 351 | "classmap": [ 352 | "tests/Test/AbstractFixerTestCase.php", 353 | "tests/Test/AbstractIntegrationCaseFactory.php", 354 | "tests/Test/AbstractIntegrationTestCase.php", 355 | "tests/Test/Assert/AssertTokensTrait.php", 356 | "tests/Test/IntegrationCase.php", 357 | "tests/Test/IntegrationCaseFactory.php", 358 | "tests/Test/IntegrationCaseFactoryInterface.php", 359 | "tests/Test/InternalIntegrationCaseFactory.php", 360 | "tests/TestCase.php" 361 | ] 362 | }, 363 | "notification-url": "https://packagist.org/downloads/", 364 | "license": [ 365 | "MIT" 366 | ], 367 | "authors": [ 368 | { 369 | "name": "Dariusz Rumiński", 370 | "email": "dariusz.ruminski@gmail.com" 371 | }, 372 | { 373 | "name": "Fabien Potencier", 374 | "email": "fabien@symfony.com" 375 | } 376 | ], 377 | "description": "A tool to automatically fix PHP code style", 378 | "time": "2018-08-23T13:15:44+00:00" 379 | }, 380 | { 381 | "name": "paragonie/random_compat", 382 | "version": "v2.0.17", 383 | "source": { 384 | "type": "git", 385 | "url": "https://github.com/paragonie/random_compat.git", 386 | "reference": "29af24f25bab834fcbb38ad2a69fa93b867e070d" 387 | }, 388 | "dist": { 389 | "type": "zip", 390 | "url": "https://api.github.com/repos/paragonie/random_compat/zipball/29af24f25bab834fcbb38ad2a69fa93b867e070d", 391 | "reference": "29af24f25bab834fcbb38ad2a69fa93b867e070d", 392 | "shasum": "" 393 | }, 394 | "require": { 395 | "php": ">=5.2.0" 396 | }, 397 | "require-dev": { 398 | "phpunit/phpunit": "4.*|5.*" 399 | }, 400 | "suggest": { 401 | "ext-libsodium": "Provides a modern crypto API that can be used to generate random bytes." 402 | }, 403 | "type": "library", 404 | "autoload": { 405 | "files": [ 406 | "lib/random.php" 407 | ] 408 | }, 409 | "notification-url": "https://packagist.org/downloads/", 410 | "license": [ 411 | "MIT" 412 | ], 413 | "authors": [ 414 | { 415 | "name": "Paragon Initiative Enterprises", 416 | "email": "security@paragonie.com", 417 | "homepage": "https://paragonie.com" 418 | } 419 | ], 420 | "description": "PHP 5.x polyfill for random_bytes() and random_int() from PHP 7", 421 | "keywords": [ 422 | "csprng", 423 | "polyfill", 424 | "pseudorandom", 425 | "random" 426 | ], 427 | "time": "2018-07-04T16:31:37+00:00" 428 | }, 429 | { 430 | "name": "php-cs-fixer/diff", 431 | "version": "v1.3.0", 432 | "source": { 433 | "type": "git", 434 | "url": "https://github.com/PHP-CS-Fixer/diff.git", 435 | "reference": "78bb099e9c16361126c86ce82ec4405ebab8e756" 436 | }, 437 | "dist": { 438 | "type": "zip", 439 | "url": "https://api.github.com/repos/PHP-CS-Fixer/diff/zipball/78bb099e9c16361126c86ce82ec4405ebab8e756", 440 | "reference": "78bb099e9c16361126c86ce82ec4405ebab8e756", 441 | "shasum": "" 442 | }, 443 | "require": { 444 | "php": "^5.6 || ^7.0" 445 | }, 446 | "require-dev": { 447 | "phpunit/phpunit": "^5.7.23 || ^6.4.3", 448 | "symfony/process": "^3.3" 449 | }, 450 | "type": "library", 451 | "autoload": { 452 | "classmap": [ 453 | "src/" 454 | ] 455 | }, 456 | "notification-url": "https://packagist.org/downloads/", 457 | "license": [ 458 | "BSD-3-Clause" 459 | ], 460 | "authors": [ 461 | { 462 | "name": "Kore Nordmann", 463 | "email": "mail@kore-nordmann.de" 464 | }, 465 | { 466 | "name": "Sebastian Bergmann", 467 | "email": "sebastian@phpunit.de" 468 | }, 469 | { 470 | "name": "SpacePossum" 471 | } 472 | ], 473 | "description": "sebastian/diff v2 backport support for PHP5.6", 474 | "homepage": "https://github.com/PHP-CS-Fixer", 475 | "keywords": [ 476 | "diff" 477 | ], 478 | "time": "2018-02-15T16:58:55+00:00" 479 | }, 480 | { 481 | "name": "psr/log", 482 | "version": "1.0.2", 483 | "source": { 484 | "type": "git", 485 | "url": "https://github.com/php-fig/log.git", 486 | "reference": "4ebe3a8bf773a19edfe0a84b6585ba3d401b724d" 487 | }, 488 | "dist": { 489 | "type": "zip", 490 | "url": "https://api.github.com/repos/php-fig/log/zipball/4ebe3a8bf773a19edfe0a84b6585ba3d401b724d", 491 | "reference": "4ebe3a8bf773a19edfe0a84b6585ba3d401b724d", 492 | "shasum": "" 493 | }, 494 | "require": { 495 | "php": ">=5.3.0" 496 | }, 497 | "type": "library", 498 | "extra": { 499 | "branch-alias": { 500 | "dev-master": "1.0.x-dev" 501 | } 502 | }, 503 | "autoload": { 504 | "psr-4": { 505 | "Psr\\Log\\": "Psr/Log/" 506 | } 507 | }, 508 | "notification-url": "https://packagist.org/downloads/", 509 | "license": [ 510 | "MIT" 511 | ], 512 | "authors": [ 513 | { 514 | "name": "PHP-FIG", 515 | "homepage": "http://www.php-fig.org/" 516 | } 517 | ], 518 | "description": "Common interface for logging libraries", 519 | "homepage": "https://github.com/php-fig/log", 520 | "keywords": [ 521 | "log", 522 | "psr", 523 | "psr-3" 524 | ], 525 | "time": "2016-10-10T12:19:37+00:00" 526 | }, 527 | { 528 | "name": "symfony/console", 529 | "version": "v3.4.15", 530 | "source": { 531 | "type": "git", 532 | "url": "https://github.com/symfony/console.git", 533 | "reference": "6b217594552b9323bcdcfc14f8a0ce126e84cd73" 534 | }, 535 | "dist": { 536 | "type": "zip", 537 | "url": "https://api.github.com/repos/symfony/console/zipball/6b217594552b9323bcdcfc14f8a0ce126e84cd73", 538 | "reference": "6b217594552b9323bcdcfc14f8a0ce126e84cd73", 539 | "shasum": "" 540 | }, 541 | "require": { 542 | "php": "^5.5.9|>=7.0.8", 543 | "symfony/debug": "~2.8|~3.0|~4.0", 544 | "symfony/polyfill-mbstring": "~1.0" 545 | }, 546 | "conflict": { 547 | "symfony/dependency-injection": "<3.4", 548 | "symfony/process": "<3.3" 549 | }, 550 | "require-dev": { 551 | "psr/log": "~1.0", 552 | "symfony/config": "~3.3|~4.0", 553 | "symfony/dependency-injection": "~3.4|~4.0", 554 | "symfony/event-dispatcher": "~2.8|~3.0|~4.0", 555 | "symfony/lock": "~3.4|~4.0", 556 | "symfony/process": "~3.3|~4.0" 557 | }, 558 | "suggest": { 559 | "psr/log-implementation": "For using the console logger", 560 | "symfony/event-dispatcher": "", 561 | "symfony/lock": "", 562 | "symfony/process": "" 563 | }, 564 | "type": "library", 565 | "extra": { 566 | "branch-alias": { 567 | "dev-master": "3.4-dev" 568 | } 569 | }, 570 | "autoload": { 571 | "psr-4": { 572 | "Symfony\\Component\\Console\\": "" 573 | }, 574 | "exclude-from-classmap": [ 575 | "/Tests/" 576 | ] 577 | }, 578 | "notification-url": "https://packagist.org/downloads/", 579 | "license": [ 580 | "MIT" 581 | ], 582 | "authors": [ 583 | { 584 | "name": "Fabien Potencier", 585 | "email": "fabien@symfony.com" 586 | }, 587 | { 588 | "name": "Symfony Community", 589 | "homepage": "https://symfony.com/contributors" 590 | } 591 | ], 592 | "description": "Symfony Console Component", 593 | "homepage": "https://symfony.com", 594 | "time": "2018-07-26T11:19:56+00:00" 595 | }, 596 | { 597 | "name": "symfony/debug", 598 | "version": "v3.4.15", 599 | "source": { 600 | "type": "git", 601 | "url": "https://github.com/symfony/debug.git", 602 | "reference": "c4625e75341e4fb309ce0c049cbf7fb84b8897cd" 603 | }, 604 | "dist": { 605 | "type": "zip", 606 | "url": "https://api.github.com/repos/symfony/debug/zipball/c4625e75341e4fb309ce0c049cbf7fb84b8897cd", 607 | "reference": "c4625e75341e4fb309ce0c049cbf7fb84b8897cd", 608 | "shasum": "" 609 | }, 610 | "require": { 611 | "php": "^5.5.9|>=7.0.8", 612 | "psr/log": "~1.0" 613 | }, 614 | "conflict": { 615 | "symfony/http-kernel": ">=2.3,<2.3.24|~2.4.0|>=2.5,<2.5.9|>=2.6,<2.6.2" 616 | }, 617 | "require-dev": { 618 | "symfony/http-kernel": "~2.8|~3.0|~4.0" 619 | }, 620 | "type": "library", 621 | "extra": { 622 | "branch-alias": { 623 | "dev-master": "3.4-dev" 624 | } 625 | }, 626 | "autoload": { 627 | "psr-4": { 628 | "Symfony\\Component\\Debug\\": "" 629 | }, 630 | "exclude-from-classmap": [ 631 | "/Tests/" 632 | ] 633 | }, 634 | "notification-url": "https://packagist.org/downloads/", 635 | "license": [ 636 | "MIT" 637 | ], 638 | "authors": [ 639 | { 640 | "name": "Fabien Potencier", 641 | "email": "fabien@symfony.com" 642 | }, 643 | { 644 | "name": "Symfony Community", 645 | "homepage": "https://symfony.com/contributors" 646 | } 647 | ], 648 | "description": "Symfony Debug Component", 649 | "homepage": "https://symfony.com", 650 | "time": "2018-08-03T10:42:44+00:00" 651 | }, 652 | { 653 | "name": "symfony/event-dispatcher", 654 | "version": "v3.4.15", 655 | "source": { 656 | "type": "git", 657 | "url": "https://github.com/symfony/event-dispatcher.git", 658 | "reference": "b2e1f19280c09a42dc64c0b72b80fe44dd6e88fb" 659 | }, 660 | "dist": { 661 | "type": "zip", 662 | "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/b2e1f19280c09a42dc64c0b72b80fe44dd6e88fb", 663 | "reference": "b2e1f19280c09a42dc64c0b72b80fe44dd6e88fb", 664 | "shasum": "" 665 | }, 666 | "require": { 667 | "php": "^5.5.9|>=7.0.8" 668 | }, 669 | "conflict": { 670 | "symfony/dependency-injection": "<3.3" 671 | }, 672 | "require-dev": { 673 | "psr/log": "~1.0", 674 | "symfony/config": "~2.8|~3.0|~4.0", 675 | "symfony/dependency-injection": "~3.3|~4.0", 676 | "symfony/expression-language": "~2.8|~3.0|~4.0", 677 | "symfony/stopwatch": "~2.8|~3.0|~4.0" 678 | }, 679 | "suggest": { 680 | "symfony/dependency-injection": "", 681 | "symfony/http-kernel": "" 682 | }, 683 | "type": "library", 684 | "extra": { 685 | "branch-alias": { 686 | "dev-master": "3.4-dev" 687 | } 688 | }, 689 | "autoload": { 690 | "psr-4": { 691 | "Symfony\\Component\\EventDispatcher\\": "" 692 | }, 693 | "exclude-from-classmap": [ 694 | "/Tests/" 695 | ] 696 | }, 697 | "notification-url": "https://packagist.org/downloads/", 698 | "license": [ 699 | "MIT" 700 | ], 701 | "authors": [ 702 | { 703 | "name": "Fabien Potencier", 704 | "email": "fabien@symfony.com" 705 | }, 706 | { 707 | "name": "Symfony Community", 708 | "homepage": "https://symfony.com/contributors" 709 | } 710 | ], 711 | "description": "Symfony EventDispatcher Component", 712 | "homepage": "https://symfony.com", 713 | "time": "2018-07-26T09:06:28+00:00" 714 | }, 715 | { 716 | "name": "symfony/filesystem", 717 | "version": "v3.4.15", 718 | "source": { 719 | "type": "git", 720 | "url": "https://github.com/symfony/filesystem.git", 721 | "reference": "285ce5005cb01a0aeaa5b0cf590bd0cc40bb631c" 722 | }, 723 | "dist": { 724 | "type": "zip", 725 | "url": "https://api.github.com/repos/symfony/filesystem/zipball/285ce5005cb01a0aeaa5b0cf590bd0cc40bb631c", 726 | "reference": "285ce5005cb01a0aeaa5b0cf590bd0cc40bb631c", 727 | "shasum": "" 728 | }, 729 | "require": { 730 | "php": "^5.5.9|>=7.0.8", 731 | "symfony/polyfill-ctype": "~1.8" 732 | }, 733 | "type": "library", 734 | "extra": { 735 | "branch-alias": { 736 | "dev-master": "3.4-dev" 737 | } 738 | }, 739 | "autoload": { 740 | "psr-4": { 741 | "Symfony\\Component\\Filesystem\\": "" 742 | }, 743 | "exclude-from-classmap": [ 744 | "/Tests/" 745 | ] 746 | }, 747 | "notification-url": "https://packagist.org/downloads/", 748 | "license": [ 749 | "MIT" 750 | ], 751 | "authors": [ 752 | { 753 | "name": "Fabien Potencier", 754 | "email": "fabien@symfony.com" 755 | }, 756 | { 757 | "name": "Symfony Community", 758 | "homepage": "https://symfony.com/contributors" 759 | } 760 | ], 761 | "description": "Symfony Filesystem Component", 762 | "homepage": "https://symfony.com", 763 | "time": "2018-08-10T07:29:05+00:00" 764 | }, 765 | { 766 | "name": "symfony/finder", 767 | "version": "v3.4.15", 768 | "source": { 769 | "type": "git", 770 | "url": "https://github.com/symfony/finder.git", 771 | "reference": "8a84fcb207451df0013b2c74cbbf1b62d47b999a" 772 | }, 773 | "dist": { 774 | "type": "zip", 775 | "url": "https://api.github.com/repos/symfony/finder/zipball/8a84fcb207451df0013b2c74cbbf1b62d47b999a", 776 | "reference": "8a84fcb207451df0013b2c74cbbf1b62d47b999a", 777 | "shasum": "" 778 | }, 779 | "require": { 780 | "php": "^5.5.9|>=7.0.8" 781 | }, 782 | "type": "library", 783 | "extra": { 784 | "branch-alias": { 785 | "dev-master": "3.4-dev" 786 | } 787 | }, 788 | "autoload": { 789 | "psr-4": { 790 | "Symfony\\Component\\Finder\\": "" 791 | }, 792 | "exclude-from-classmap": [ 793 | "/Tests/" 794 | ] 795 | }, 796 | "notification-url": "https://packagist.org/downloads/", 797 | "license": [ 798 | "MIT" 799 | ], 800 | "authors": [ 801 | { 802 | "name": "Fabien Potencier", 803 | "email": "fabien@symfony.com" 804 | }, 805 | { 806 | "name": "Symfony Community", 807 | "homepage": "https://symfony.com/contributors" 808 | } 809 | ], 810 | "description": "Symfony Finder Component", 811 | "homepage": "https://symfony.com", 812 | "time": "2018-07-26T11:19:56+00:00" 813 | }, 814 | { 815 | "name": "symfony/options-resolver", 816 | "version": "v3.4.15", 817 | "source": { 818 | "type": "git", 819 | "url": "https://github.com/symfony/options-resolver.git", 820 | "reference": "6debc476953a45969ab39afe8dee0b825f356dc7" 821 | }, 822 | "dist": { 823 | "type": "zip", 824 | "url": "https://api.github.com/repos/symfony/options-resolver/zipball/6debc476953a45969ab39afe8dee0b825f356dc7", 825 | "reference": "6debc476953a45969ab39afe8dee0b825f356dc7", 826 | "shasum": "" 827 | }, 828 | "require": { 829 | "php": "^5.5.9|>=7.0.8" 830 | }, 831 | "type": "library", 832 | "extra": { 833 | "branch-alias": { 834 | "dev-master": "3.4-dev" 835 | } 836 | }, 837 | "autoload": { 838 | "psr-4": { 839 | "Symfony\\Component\\OptionsResolver\\": "" 840 | }, 841 | "exclude-from-classmap": [ 842 | "/Tests/" 843 | ] 844 | }, 845 | "notification-url": "https://packagist.org/downloads/", 846 | "license": [ 847 | "MIT" 848 | ], 849 | "authors": [ 850 | { 851 | "name": "Fabien Potencier", 852 | "email": "fabien@symfony.com" 853 | }, 854 | { 855 | "name": "Symfony Community", 856 | "homepage": "https://symfony.com/contributors" 857 | } 858 | ], 859 | "description": "Symfony OptionsResolver Component", 860 | "homepage": "https://symfony.com", 861 | "keywords": [ 862 | "config", 863 | "configuration", 864 | "options" 865 | ], 866 | "time": "2018-07-26T08:45:46+00:00" 867 | }, 868 | { 869 | "name": "symfony/polyfill-ctype", 870 | "version": "v1.9.0", 871 | "source": { 872 | "type": "git", 873 | "url": "https://github.com/symfony/polyfill-ctype.git", 874 | "reference": "e3d826245268269cd66f8326bd8bc066687b4a19" 875 | }, 876 | "dist": { 877 | "type": "zip", 878 | "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/e3d826245268269cd66f8326bd8bc066687b4a19", 879 | "reference": "e3d826245268269cd66f8326bd8bc066687b4a19", 880 | "shasum": "" 881 | }, 882 | "require": { 883 | "php": ">=5.3.3" 884 | }, 885 | "suggest": { 886 | "ext-ctype": "For best performance" 887 | }, 888 | "type": "library", 889 | "extra": { 890 | "branch-alias": { 891 | "dev-master": "1.9-dev" 892 | } 893 | }, 894 | "autoload": { 895 | "psr-4": { 896 | "Symfony\\Polyfill\\Ctype\\": "" 897 | }, 898 | "files": [ 899 | "bootstrap.php" 900 | ] 901 | }, 902 | "notification-url": "https://packagist.org/downloads/", 903 | "license": [ 904 | "MIT" 905 | ], 906 | "authors": [ 907 | { 908 | "name": "Symfony Community", 909 | "homepage": "https://symfony.com/contributors" 910 | }, 911 | { 912 | "name": "Gert de Pagter", 913 | "email": "BackEndTea@gmail.com" 914 | } 915 | ], 916 | "description": "Symfony polyfill for ctype functions", 917 | "homepage": "https://symfony.com", 918 | "keywords": [ 919 | "compatibility", 920 | "ctype", 921 | "polyfill", 922 | "portable" 923 | ], 924 | "time": "2018-08-06T14:22:27+00:00" 925 | }, 926 | { 927 | "name": "symfony/polyfill-mbstring", 928 | "version": "v1.9.0", 929 | "source": { 930 | "type": "git", 931 | "url": "https://github.com/symfony/polyfill-mbstring.git", 932 | "reference": "d0cd638f4634c16d8df4508e847f14e9e43168b8" 933 | }, 934 | "dist": { 935 | "type": "zip", 936 | "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/d0cd638f4634c16d8df4508e847f14e9e43168b8", 937 | "reference": "d0cd638f4634c16d8df4508e847f14e9e43168b8", 938 | "shasum": "" 939 | }, 940 | "require": { 941 | "php": ">=5.3.3" 942 | }, 943 | "suggest": { 944 | "ext-mbstring": "For best performance" 945 | }, 946 | "type": "library", 947 | "extra": { 948 | "branch-alias": { 949 | "dev-master": "1.9-dev" 950 | } 951 | }, 952 | "autoload": { 953 | "psr-4": { 954 | "Symfony\\Polyfill\\Mbstring\\": "" 955 | }, 956 | "files": [ 957 | "bootstrap.php" 958 | ] 959 | }, 960 | "notification-url": "https://packagist.org/downloads/", 961 | "license": [ 962 | "MIT" 963 | ], 964 | "authors": [ 965 | { 966 | "name": "Nicolas Grekas", 967 | "email": "p@tchwork.com" 968 | }, 969 | { 970 | "name": "Symfony Community", 971 | "homepage": "https://symfony.com/contributors" 972 | } 973 | ], 974 | "description": "Symfony polyfill for the Mbstring extension", 975 | "homepage": "https://symfony.com", 976 | "keywords": [ 977 | "compatibility", 978 | "mbstring", 979 | "polyfill", 980 | "portable", 981 | "shim" 982 | ], 983 | "time": "2018-08-06T14:22:27+00:00" 984 | }, 985 | { 986 | "name": "symfony/polyfill-php70", 987 | "version": "v1.9.0", 988 | "source": { 989 | "type": "git", 990 | "url": "https://github.com/symfony/polyfill-php70.git", 991 | "reference": "1e24b0c4a56d55aaf368763a06c6d1c7d3194934" 992 | }, 993 | "dist": { 994 | "type": "zip", 995 | "url": "https://api.github.com/repos/symfony/polyfill-php70/zipball/1e24b0c4a56d55aaf368763a06c6d1c7d3194934", 996 | "reference": "1e24b0c4a56d55aaf368763a06c6d1c7d3194934", 997 | "shasum": "" 998 | }, 999 | "require": { 1000 | "paragonie/random_compat": "~1.0|~2.0|~9.99", 1001 | "php": ">=5.3.3" 1002 | }, 1003 | "type": "library", 1004 | "extra": { 1005 | "branch-alias": { 1006 | "dev-master": "1.9-dev" 1007 | } 1008 | }, 1009 | "autoload": { 1010 | "psr-4": { 1011 | "Symfony\\Polyfill\\Php70\\": "" 1012 | }, 1013 | "files": [ 1014 | "bootstrap.php" 1015 | ], 1016 | "classmap": [ 1017 | "Resources/stubs" 1018 | ] 1019 | }, 1020 | "notification-url": "https://packagist.org/downloads/", 1021 | "license": [ 1022 | "MIT" 1023 | ], 1024 | "authors": [ 1025 | { 1026 | "name": "Nicolas Grekas", 1027 | "email": "p@tchwork.com" 1028 | }, 1029 | { 1030 | "name": "Symfony Community", 1031 | "homepage": "https://symfony.com/contributors" 1032 | } 1033 | ], 1034 | "description": "Symfony polyfill backporting some PHP 7.0+ features to lower PHP versions", 1035 | "homepage": "https://symfony.com", 1036 | "keywords": [ 1037 | "compatibility", 1038 | "polyfill", 1039 | "portable", 1040 | "shim" 1041 | ], 1042 | "time": "2018-08-06T14:22:27+00:00" 1043 | }, 1044 | { 1045 | "name": "symfony/polyfill-php72", 1046 | "version": "v1.9.0", 1047 | "source": { 1048 | "type": "git", 1049 | "url": "https://github.com/symfony/polyfill-php72.git", 1050 | "reference": "95c50420b0baed23852452a7f0c7b527303ed5ae" 1051 | }, 1052 | "dist": { 1053 | "type": "zip", 1054 | "url": "https://api.github.com/repos/symfony/polyfill-php72/zipball/95c50420b0baed23852452a7f0c7b527303ed5ae", 1055 | "reference": "95c50420b0baed23852452a7f0c7b527303ed5ae", 1056 | "shasum": "" 1057 | }, 1058 | "require": { 1059 | "php": ">=5.3.3" 1060 | }, 1061 | "type": "library", 1062 | "extra": { 1063 | "branch-alias": { 1064 | "dev-master": "1.9-dev" 1065 | } 1066 | }, 1067 | "autoload": { 1068 | "psr-4": { 1069 | "Symfony\\Polyfill\\Php72\\": "" 1070 | }, 1071 | "files": [ 1072 | "bootstrap.php" 1073 | ] 1074 | }, 1075 | "notification-url": "https://packagist.org/downloads/", 1076 | "license": [ 1077 | "MIT" 1078 | ], 1079 | "authors": [ 1080 | { 1081 | "name": "Nicolas Grekas", 1082 | "email": "p@tchwork.com" 1083 | }, 1084 | { 1085 | "name": "Symfony Community", 1086 | "homepage": "https://symfony.com/contributors" 1087 | } 1088 | ], 1089 | "description": "Symfony polyfill backporting some PHP 7.2+ features to lower PHP versions", 1090 | "homepage": "https://symfony.com", 1091 | "keywords": [ 1092 | "compatibility", 1093 | "polyfill", 1094 | "portable", 1095 | "shim" 1096 | ], 1097 | "time": "2018-08-06T14:22:27+00:00" 1098 | }, 1099 | { 1100 | "name": "symfony/process", 1101 | "version": "v3.4.15", 1102 | "source": { 1103 | "type": "git", 1104 | "url": "https://github.com/symfony/process.git", 1105 | "reference": "4d6b125d5293cbceedc2aa10f2c71617e76262e7" 1106 | }, 1107 | "dist": { 1108 | "type": "zip", 1109 | "url": "https://api.github.com/repos/symfony/process/zipball/4d6b125d5293cbceedc2aa10f2c71617e76262e7", 1110 | "reference": "4d6b125d5293cbceedc2aa10f2c71617e76262e7", 1111 | "shasum": "" 1112 | }, 1113 | "require": { 1114 | "php": "^5.5.9|>=7.0.8" 1115 | }, 1116 | "type": "library", 1117 | "extra": { 1118 | "branch-alias": { 1119 | "dev-master": "3.4-dev" 1120 | } 1121 | }, 1122 | "autoload": { 1123 | "psr-4": { 1124 | "Symfony\\Component\\Process\\": "" 1125 | }, 1126 | "exclude-from-classmap": [ 1127 | "/Tests/" 1128 | ] 1129 | }, 1130 | "notification-url": "https://packagist.org/downloads/", 1131 | "license": [ 1132 | "MIT" 1133 | ], 1134 | "authors": [ 1135 | { 1136 | "name": "Fabien Potencier", 1137 | "email": "fabien@symfony.com" 1138 | }, 1139 | { 1140 | "name": "Symfony Community", 1141 | "homepage": "https://symfony.com/contributors" 1142 | } 1143 | ], 1144 | "description": "Symfony Process Component", 1145 | "homepage": "https://symfony.com", 1146 | "time": "2018-08-03T10:42:44+00:00" 1147 | }, 1148 | { 1149 | "name": "symfony/stopwatch", 1150 | "version": "v3.4.15", 1151 | "source": { 1152 | "type": "git", 1153 | "url": "https://github.com/symfony/stopwatch.git", 1154 | "reference": "deda2765e8dab2fc38492e926ea690f2a681f59d" 1155 | }, 1156 | "dist": { 1157 | "type": "zip", 1158 | "url": "https://api.github.com/repos/symfony/stopwatch/zipball/deda2765e8dab2fc38492e926ea690f2a681f59d", 1159 | "reference": "deda2765e8dab2fc38492e926ea690f2a681f59d", 1160 | "shasum": "" 1161 | }, 1162 | "require": { 1163 | "php": "^5.5.9|>=7.0.8" 1164 | }, 1165 | "type": "library", 1166 | "extra": { 1167 | "branch-alias": { 1168 | "dev-master": "3.4-dev" 1169 | } 1170 | }, 1171 | "autoload": { 1172 | "psr-4": { 1173 | "Symfony\\Component\\Stopwatch\\": "" 1174 | }, 1175 | "exclude-from-classmap": [ 1176 | "/Tests/" 1177 | ] 1178 | }, 1179 | "notification-url": "https://packagist.org/downloads/", 1180 | "license": [ 1181 | "MIT" 1182 | ], 1183 | "authors": [ 1184 | { 1185 | "name": "Fabien Potencier", 1186 | "email": "fabien@symfony.com" 1187 | }, 1188 | { 1189 | "name": "Symfony Community", 1190 | "homepage": "https://symfony.com/contributors" 1191 | } 1192 | ], 1193 | "description": "Symfony Stopwatch Component", 1194 | "homepage": "https://symfony.com", 1195 | "time": "2018-07-26T10:03:52+00:00" 1196 | } 1197 | ], 1198 | "packages-dev": [ 1199 | { 1200 | "name": "doctrine/instantiator", 1201 | "version": "1.0.5", 1202 | "source": { 1203 | "type": "git", 1204 | "url": "https://github.com/doctrine/instantiator.git", 1205 | "reference": "8e884e78f9f0eb1329e445619e04456e64d8051d" 1206 | }, 1207 | "dist": { 1208 | "type": "zip", 1209 | "url": "https://api.github.com/repos/doctrine/instantiator/zipball/8e884e78f9f0eb1329e445619e04456e64d8051d", 1210 | "reference": "8e884e78f9f0eb1329e445619e04456e64d8051d", 1211 | "shasum": "" 1212 | }, 1213 | "require": { 1214 | "php": ">=5.3,<8.0-DEV" 1215 | }, 1216 | "require-dev": { 1217 | "athletic/athletic": "~0.1.8", 1218 | "ext-pdo": "*", 1219 | "ext-phar": "*", 1220 | "phpunit/phpunit": "~4.0", 1221 | "squizlabs/php_codesniffer": "~2.0" 1222 | }, 1223 | "type": "library", 1224 | "extra": { 1225 | "branch-alias": { 1226 | "dev-master": "1.0.x-dev" 1227 | } 1228 | }, 1229 | "autoload": { 1230 | "psr-4": { 1231 | "Doctrine\\Instantiator\\": "src/Doctrine/Instantiator/" 1232 | } 1233 | }, 1234 | "notification-url": "https://packagist.org/downloads/", 1235 | "license": [ 1236 | "MIT" 1237 | ], 1238 | "authors": [ 1239 | { 1240 | "name": "Marco Pivetta", 1241 | "email": "ocramius@gmail.com", 1242 | "homepage": "http://ocramius.github.com/" 1243 | } 1244 | ], 1245 | "description": "A small, lightweight utility to instantiate objects in PHP without invoking their constructors", 1246 | "homepage": "https://github.com/doctrine/instantiator", 1247 | "keywords": [ 1248 | "constructor", 1249 | "instantiate" 1250 | ], 1251 | "time": "2015-06-14T21:17:01+00:00" 1252 | }, 1253 | { 1254 | "name": "myclabs/deep-copy", 1255 | "version": "1.7.0", 1256 | "source": { 1257 | "type": "git", 1258 | "url": "https://github.com/myclabs/DeepCopy.git", 1259 | "reference": "3b8a3a99ba1f6a3952ac2747d989303cbd6b7a3e" 1260 | }, 1261 | "dist": { 1262 | "type": "zip", 1263 | "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/3b8a3a99ba1f6a3952ac2747d989303cbd6b7a3e", 1264 | "reference": "3b8a3a99ba1f6a3952ac2747d989303cbd6b7a3e", 1265 | "shasum": "" 1266 | }, 1267 | "require": { 1268 | "php": "^5.6 || ^7.0" 1269 | }, 1270 | "require-dev": { 1271 | "doctrine/collections": "^1.0", 1272 | "doctrine/common": "^2.6", 1273 | "phpunit/phpunit": "^4.1" 1274 | }, 1275 | "type": "library", 1276 | "autoload": { 1277 | "psr-4": { 1278 | "DeepCopy\\": "src/DeepCopy/" 1279 | }, 1280 | "files": [ 1281 | "src/DeepCopy/deep_copy.php" 1282 | ] 1283 | }, 1284 | "notification-url": "https://packagist.org/downloads/", 1285 | "license": [ 1286 | "MIT" 1287 | ], 1288 | "description": "Create deep copies (clones) of your objects", 1289 | "keywords": [ 1290 | "clone", 1291 | "copy", 1292 | "duplicate", 1293 | "object", 1294 | "object graph" 1295 | ], 1296 | "time": "2017-10-19T19:58:43+00:00" 1297 | }, 1298 | { 1299 | "name": "phpdocumentor/reflection-common", 1300 | "version": "1.0.1", 1301 | "source": { 1302 | "type": "git", 1303 | "url": "https://github.com/phpDocumentor/ReflectionCommon.git", 1304 | "reference": "21bdeb5f65d7ebf9f43b1b25d404f87deab5bfb6" 1305 | }, 1306 | "dist": { 1307 | "type": "zip", 1308 | "url": "https://api.github.com/repos/phpDocumentor/ReflectionCommon/zipball/21bdeb5f65d7ebf9f43b1b25d404f87deab5bfb6", 1309 | "reference": "21bdeb5f65d7ebf9f43b1b25d404f87deab5bfb6", 1310 | "shasum": "" 1311 | }, 1312 | "require": { 1313 | "php": ">=5.5" 1314 | }, 1315 | "require-dev": { 1316 | "phpunit/phpunit": "^4.6" 1317 | }, 1318 | "type": "library", 1319 | "extra": { 1320 | "branch-alias": { 1321 | "dev-master": "1.0.x-dev" 1322 | } 1323 | }, 1324 | "autoload": { 1325 | "psr-4": { 1326 | "phpDocumentor\\Reflection\\": [ 1327 | "src" 1328 | ] 1329 | } 1330 | }, 1331 | "notification-url": "https://packagist.org/downloads/", 1332 | "license": [ 1333 | "MIT" 1334 | ], 1335 | "authors": [ 1336 | { 1337 | "name": "Jaap van Otterdijk", 1338 | "email": "opensource@ijaap.nl" 1339 | } 1340 | ], 1341 | "description": "Common reflection classes used by phpdocumentor to reflect the code structure", 1342 | "homepage": "http://www.phpdoc.org", 1343 | "keywords": [ 1344 | "FQSEN", 1345 | "phpDocumentor", 1346 | "phpdoc", 1347 | "reflection", 1348 | "static analysis" 1349 | ], 1350 | "time": "2017-09-11T18:02:19+00:00" 1351 | }, 1352 | { 1353 | "name": "phpdocumentor/reflection-docblock", 1354 | "version": "3.3.2", 1355 | "source": { 1356 | "type": "git", 1357 | "url": "https://github.com/phpDocumentor/ReflectionDocBlock.git", 1358 | "reference": "bf329f6c1aadea3299f08ee804682b7c45b326a2" 1359 | }, 1360 | "dist": { 1361 | "type": "zip", 1362 | "url": "https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/bf329f6c1aadea3299f08ee804682b7c45b326a2", 1363 | "reference": "bf329f6c1aadea3299f08ee804682b7c45b326a2", 1364 | "shasum": "" 1365 | }, 1366 | "require": { 1367 | "php": "^5.6 || ^7.0", 1368 | "phpdocumentor/reflection-common": "^1.0.0", 1369 | "phpdocumentor/type-resolver": "^0.4.0", 1370 | "webmozart/assert": "^1.0" 1371 | }, 1372 | "require-dev": { 1373 | "mockery/mockery": "^0.9.4", 1374 | "phpunit/phpunit": "^4.4" 1375 | }, 1376 | "type": "library", 1377 | "autoload": { 1378 | "psr-4": { 1379 | "phpDocumentor\\Reflection\\": [ 1380 | "src/" 1381 | ] 1382 | } 1383 | }, 1384 | "notification-url": "https://packagist.org/downloads/", 1385 | "license": [ 1386 | "MIT" 1387 | ], 1388 | "authors": [ 1389 | { 1390 | "name": "Mike van Riel", 1391 | "email": "me@mikevanriel.com" 1392 | } 1393 | ], 1394 | "description": "With this component, a library can provide support for annotations via DocBlocks or otherwise retrieve information that is embedded in a DocBlock.", 1395 | "time": "2017-11-10T14:09:06+00:00" 1396 | }, 1397 | { 1398 | "name": "phpdocumentor/type-resolver", 1399 | "version": "0.4.0", 1400 | "source": { 1401 | "type": "git", 1402 | "url": "https://github.com/phpDocumentor/TypeResolver.git", 1403 | "reference": "9c977708995954784726e25d0cd1dddf4e65b0f7" 1404 | }, 1405 | "dist": { 1406 | "type": "zip", 1407 | "url": "https://api.github.com/repos/phpDocumentor/TypeResolver/zipball/9c977708995954784726e25d0cd1dddf4e65b0f7", 1408 | "reference": "9c977708995954784726e25d0cd1dddf4e65b0f7", 1409 | "shasum": "" 1410 | }, 1411 | "require": { 1412 | "php": "^5.5 || ^7.0", 1413 | "phpdocumentor/reflection-common": "^1.0" 1414 | }, 1415 | "require-dev": { 1416 | "mockery/mockery": "^0.9.4", 1417 | "phpunit/phpunit": "^5.2||^4.8.24" 1418 | }, 1419 | "type": "library", 1420 | "extra": { 1421 | "branch-alias": { 1422 | "dev-master": "1.0.x-dev" 1423 | } 1424 | }, 1425 | "autoload": { 1426 | "psr-4": { 1427 | "phpDocumentor\\Reflection\\": [ 1428 | "src/" 1429 | ] 1430 | } 1431 | }, 1432 | "notification-url": "https://packagist.org/downloads/", 1433 | "license": [ 1434 | "MIT" 1435 | ], 1436 | "authors": [ 1437 | { 1438 | "name": "Mike van Riel", 1439 | "email": "me@mikevanriel.com" 1440 | } 1441 | ], 1442 | "time": "2017-07-14T14:27:02+00:00" 1443 | }, 1444 | { 1445 | "name": "phpspec/prophecy", 1446 | "version": "1.8.0", 1447 | "source": { 1448 | "type": "git", 1449 | "url": "https://github.com/phpspec/prophecy.git", 1450 | "reference": "4ba436b55987b4bf311cb7c6ba82aa528aac0a06" 1451 | }, 1452 | "dist": { 1453 | "type": "zip", 1454 | "url": "https://api.github.com/repos/phpspec/prophecy/zipball/4ba436b55987b4bf311cb7c6ba82aa528aac0a06", 1455 | "reference": "4ba436b55987b4bf311cb7c6ba82aa528aac0a06", 1456 | "shasum": "" 1457 | }, 1458 | "require": { 1459 | "doctrine/instantiator": "^1.0.2", 1460 | "php": "^5.3|^7.0", 1461 | "phpdocumentor/reflection-docblock": "^2.0|^3.0.2|^4.0", 1462 | "sebastian/comparator": "^1.1|^2.0|^3.0", 1463 | "sebastian/recursion-context": "^1.0|^2.0|^3.0" 1464 | }, 1465 | "require-dev": { 1466 | "phpspec/phpspec": "^2.5|^3.2", 1467 | "phpunit/phpunit": "^4.8.35 || ^5.7 || ^6.5 || ^7.1" 1468 | }, 1469 | "type": "library", 1470 | "extra": { 1471 | "branch-alias": { 1472 | "dev-master": "1.8.x-dev" 1473 | } 1474 | }, 1475 | "autoload": { 1476 | "psr-0": { 1477 | "Prophecy\\": "src/" 1478 | } 1479 | }, 1480 | "notification-url": "https://packagist.org/downloads/", 1481 | "license": [ 1482 | "MIT" 1483 | ], 1484 | "authors": [ 1485 | { 1486 | "name": "Konstantin Kudryashov", 1487 | "email": "ever.zet@gmail.com", 1488 | "homepage": "http://everzet.com" 1489 | }, 1490 | { 1491 | "name": "Marcello Duarte", 1492 | "email": "marcello.duarte@gmail.com" 1493 | } 1494 | ], 1495 | "description": "Highly opinionated mocking framework for PHP 5.3+", 1496 | "homepage": "https://github.com/phpspec/prophecy", 1497 | "keywords": [ 1498 | "Double", 1499 | "Dummy", 1500 | "fake", 1501 | "mock", 1502 | "spy", 1503 | "stub" 1504 | ], 1505 | "time": "2018-08-05T17:53:17+00:00" 1506 | }, 1507 | { 1508 | "name": "phpunit/php-code-coverage", 1509 | "version": "4.0.8", 1510 | "source": { 1511 | "type": "git", 1512 | "url": "https://github.com/sebastianbergmann/php-code-coverage.git", 1513 | "reference": "ef7b2f56815df854e66ceaee8ebe9393ae36a40d" 1514 | }, 1515 | "dist": { 1516 | "type": "zip", 1517 | "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/ef7b2f56815df854e66ceaee8ebe9393ae36a40d", 1518 | "reference": "ef7b2f56815df854e66ceaee8ebe9393ae36a40d", 1519 | "shasum": "" 1520 | }, 1521 | "require": { 1522 | "ext-dom": "*", 1523 | "ext-xmlwriter": "*", 1524 | "php": "^5.6 || ^7.0", 1525 | "phpunit/php-file-iterator": "^1.3", 1526 | "phpunit/php-text-template": "^1.2", 1527 | "phpunit/php-token-stream": "^1.4.2 || ^2.0", 1528 | "sebastian/code-unit-reverse-lookup": "^1.0", 1529 | "sebastian/environment": "^1.3.2 || ^2.0", 1530 | "sebastian/version": "^1.0 || ^2.0" 1531 | }, 1532 | "require-dev": { 1533 | "ext-xdebug": "^2.1.4", 1534 | "phpunit/phpunit": "^5.7" 1535 | }, 1536 | "suggest": { 1537 | "ext-xdebug": "^2.5.1" 1538 | }, 1539 | "type": "library", 1540 | "extra": { 1541 | "branch-alias": { 1542 | "dev-master": "4.0.x-dev" 1543 | } 1544 | }, 1545 | "autoload": { 1546 | "classmap": [ 1547 | "src/" 1548 | ] 1549 | }, 1550 | "notification-url": "https://packagist.org/downloads/", 1551 | "license": [ 1552 | "BSD-3-Clause" 1553 | ], 1554 | "authors": [ 1555 | { 1556 | "name": "Sebastian Bergmann", 1557 | "email": "sb@sebastian-bergmann.de", 1558 | "role": "lead" 1559 | } 1560 | ], 1561 | "description": "Library that provides collection, processing, and rendering functionality for PHP code coverage information.", 1562 | "homepage": "https://github.com/sebastianbergmann/php-code-coverage", 1563 | "keywords": [ 1564 | "coverage", 1565 | "testing", 1566 | "xunit" 1567 | ], 1568 | "time": "2017-04-02T07:44:40+00:00" 1569 | }, 1570 | { 1571 | "name": "phpunit/php-file-iterator", 1572 | "version": "1.4.5", 1573 | "source": { 1574 | "type": "git", 1575 | "url": "https://github.com/sebastianbergmann/php-file-iterator.git", 1576 | "reference": "730b01bc3e867237eaac355e06a36b85dd93a8b4" 1577 | }, 1578 | "dist": { 1579 | "type": "zip", 1580 | "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/730b01bc3e867237eaac355e06a36b85dd93a8b4", 1581 | "reference": "730b01bc3e867237eaac355e06a36b85dd93a8b4", 1582 | "shasum": "" 1583 | }, 1584 | "require": { 1585 | "php": ">=5.3.3" 1586 | }, 1587 | "type": "library", 1588 | "extra": { 1589 | "branch-alias": { 1590 | "dev-master": "1.4.x-dev" 1591 | } 1592 | }, 1593 | "autoload": { 1594 | "classmap": [ 1595 | "src/" 1596 | ] 1597 | }, 1598 | "notification-url": "https://packagist.org/downloads/", 1599 | "license": [ 1600 | "BSD-3-Clause" 1601 | ], 1602 | "authors": [ 1603 | { 1604 | "name": "Sebastian Bergmann", 1605 | "email": "sb@sebastian-bergmann.de", 1606 | "role": "lead" 1607 | } 1608 | ], 1609 | "description": "FilterIterator implementation that filters files based on a list of suffixes.", 1610 | "homepage": "https://github.com/sebastianbergmann/php-file-iterator/", 1611 | "keywords": [ 1612 | "filesystem", 1613 | "iterator" 1614 | ], 1615 | "time": "2017-11-27T13:52:08+00:00" 1616 | }, 1617 | { 1618 | "name": "phpunit/php-text-template", 1619 | "version": "1.2.1", 1620 | "source": { 1621 | "type": "git", 1622 | "url": "https://github.com/sebastianbergmann/php-text-template.git", 1623 | "reference": "31f8b717e51d9a2afca6c9f046f5d69fc27c8686" 1624 | }, 1625 | "dist": { 1626 | "type": "zip", 1627 | "url": "https://api.github.com/repos/sebastianbergmann/php-text-template/zipball/31f8b717e51d9a2afca6c9f046f5d69fc27c8686", 1628 | "reference": "31f8b717e51d9a2afca6c9f046f5d69fc27c8686", 1629 | "shasum": "" 1630 | }, 1631 | "require": { 1632 | "php": ">=5.3.3" 1633 | }, 1634 | "type": "library", 1635 | "autoload": { 1636 | "classmap": [ 1637 | "src/" 1638 | ] 1639 | }, 1640 | "notification-url": "https://packagist.org/downloads/", 1641 | "license": [ 1642 | "BSD-3-Clause" 1643 | ], 1644 | "authors": [ 1645 | { 1646 | "name": "Sebastian Bergmann", 1647 | "email": "sebastian@phpunit.de", 1648 | "role": "lead" 1649 | } 1650 | ], 1651 | "description": "Simple template engine.", 1652 | "homepage": "https://github.com/sebastianbergmann/php-text-template/", 1653 | "keywords": [ 1654 | "template" 1655 | ], 1656 | "time": "2015-06-21T13:50:34+00:00" 1657 | }, 1658 | { 1659 | "name": "phpunit/php-timer", 1660 | "version": "1.0.9", 1661 | "source": { 1662 | "type": "git", 1663 | "url": "https://github.com/sebastianbergmann/php-timer.git", 1664 | "reference": "3dcf38ca72b158baf0bc245e9184d3fdffa9c46f" 1665 | }, 1666 | "dist": { 1667 | "type": "zip", 1668 | "url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/3dcf38ca72b158baf0bc245e9184d3fdffa9c46f", 1669 | "reference": "3dcf38ca72b158baf0bc245e9184d3fdffa9c46f", 1670 | "shasum": "" 1671 | }, 1672 | "require": { 1673 | "php": "^5.3.3 || ^7.0" 1674 | }, 1675 | "require-dev": { 1676 | "phpunit/phpunit": "^4.8.35 || ^5.7 || ^6.0" 1677 | }, 1678 | "type": "library", 1679 | "extra": { 1680 | "branch-alias": { 1681 | "dev-master": "1.0-dev" 1682 | } 1683 | }, 1684 | "autoload": { 1685 | "classmap": [ 1686 | "src/" 1687 | ] 1688 | }, 1689 | "notification-url": "https://packagist.org/downloads/", 1690 | "license": [ 1691 | "BSD-3-Clause" 1692 | ], 1693 | "authors": [ 1694 | { 1695 | "name": "Sebastian Bergmann", 1696 | "email": "sb@sebastian-bergmann.de", 1697 | "role": "lead" 1698 | } 1699 | ], 1700 | "description": "Utility class for timing", 1701 | "homepage": "https://github.com/sebastianbergmann/php-timer/", 1702 | "keywords": [ 1703 | "timer" 1704 | ], 1705 | "time": "2017-02-26T11:10:40+00:00" 1706 | }, 1707 | { 1708 | "name": "phpunit/php-token-stream", 1709 | "version": "1.4.12", 1710 | "source": { 1711 | "type": "git", 1712 | "url": "https://github.com/sebastianbergmann/php-token-stream.git", 1713 | "reference": "1ce90ba27c42e4e44e6d8458241466380b51fa16" 1714 | }, 1715 | "dist": { 1716 | "type": "zip", 1717 | "url": "https://api.github.com/repos/sebastianbergmann/php-token-stream/zipball/1ce90ba27c42e4e44e6d8458241466380b51fa16", 1718 | "reference": "1ce90ba27c42e4e44e6d8458241466380b51fa16", 1719 | "shasum": "" 1720 | }, 1721 | "require": { 1722 | "ext-tokenizer": "*", 1723 | "php": ">=5.3.3" 1724 | }, 1725 | "require-dev": { 1726 | "phpunit/phpunit": "~4.2" 1727 | }, 1728 | "type": "library", 1729 | "extra": { 1730 | "branch-alias": { 1731 | "dev-master": "1.4-dev" 1732 | } 1733 | }, 1734 | "autoload": { 1735 | "classmap": [ 1736 | "src/" 1737 | ] 1738 | }, 1739 | "notification-url": "https://packagist.org/downloads/", 1740 | "license": [ 1741 | "BSD-3-Clause" 1742 | ], 1743 | "authors": [ 1744 | { 1745 | "name": "Sebastian Bergmann", 1746 | "email": "sebastian@phpunit.de" 1747 | } 1748 | ], 1749 | "description": "Wrapper around PHP's tokenizer extension.", 1750 | "homepage": "https://github.com/sebastianbergmann/php-token-stream/", 1751 | "keywords": [ 1752 | "tokenizer" 1753 | ], 1754 | "time": "2017-12-04T08:55:13+00:00" 1755 | }, 1756 | { 1757 | "name": "phpunit/phpunit", 1758 | "version": "5.4.8", 1759 | "source": { 1760 | "type": "git", 1761 | "url": "https://github.com/sebastianbergmann/phpunit.git", 1762 | "reference": "3132365e1430c091f208e120b8845d39c25f20e6" 1763 | }, 1764 | "dist": { 1765 | "type": "zip", 1766 | "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/3132365e1430c091f208e120b8845d39c25f20e6", 1767 | "reference": "3132365e1430c091f208e120b8845d39c25f20e6", 1768 | "shasum": "" 1769 | }, 1770 | "require": { 1771 | "ext-dom": "*", 1772 | "ext-json": "*", 1773 | "ext-pcre": "*", 1774 | "ext-reflection": "*", 1775 | "ext-spl": "*", 1776 | "myclabs/deep-copy": "~1.3", 1777 | "php": "^5.6 || ^7.0", 1778 | "phpspec/prophecy": "^1.3.1", 1779 | "phpunit/php-code-coverage": "^4.0.1", 1780 | "phpunit/php-file-iterator": "~1.4", 1781 | "phpunit/php-text-template": "~1.2", 1782 | "phpunit/php-timer": "^1.0.6", 1783 | "phpunit/phpunit-mock-objects": "^3.2", 1784 | "sebastian/comparator": "~1.1", 1785 | "sebastian/diff": "~1.2", 1786 | "sebastian/environment": "^1.3 || ^2.0", 1787 | "sebastian/exporter": "~1.2", 1788 | "sebastian/global-state": "~1.0", 1789 | "sebastian/object-enumerator": "~1.0", 1790 | "sebastian/resource-operations": "~1.0", 1791 | "sebastian/version": "~1.0|~2.0", 1792 | "symfony/yaml": "~2.1|~3.0" 1793 | }, 1794 | "conflict": { 1795 | "phpdocumentor/reflection-docblock": "3.0.2" 1796 | }, 1797 | "suggest": { 1798 | "phpunit/php-invoker": "~1.1" 1799 | }, 1800 | "bin": [ 1801 | "phpunit" 1802 | ], 1803 | "type": "library", 1804 | "extra": { 1805 | "branch-alias": { 1806 | "dev-master": "5.4.x-dev" 1807 | } 1808 | }, 1809 | "autoload": { 1810 | "classmap": [ 1811 | "src/" 1812 | ] 1813 | }, 1814 | "notification-url": "https://packagist.org/downloads/", 1815 | "license": [ 1816 | "BSD-3-Clause" 1817 | ], 1818 | "authors": [ 1819 | { 1820 | "name": "Sebastian Bergmann", 1821 | "email": "sebastian@phpunit.de", 1822 | "role": "lead" 1823 | } 1824 | ], 1825 | "description": "The PHP Unit Testing framework.", 1826 | "homepage": "https://phpunit.de/", 1827 | "keywords": [ 1828 | "phpunit", 1829 | "testing", 1830 | "xunit" 1831 | ], 1832 | "time": "2016-07-26T14:48:00+00:00" 1833 | }, 1834 | { 1835 | "name": "phpunit/phpunit-mock-objects", 1836 | "version": "3.4.4", 1837 | "source": { 1838 | "type": "git", 1839 | "url": "https://github.com/sebastianbergmann/phpunit-mock-objects.git", 1840 | "reference": "a23b761686d50a560cc56233b9ecf49597cc9118" 1841 | }, 1842 | "dist": { 1843 | "type": "zip", 1844 | "url": "https://api.github.com/repos/sebastianbergmann/phpunit-mock-objects/zipball/a23b761686d50a560cc56233b9ecf49597cc9118", 1845 | "reference": "a23b761686d50a560cc56233b9ecf49597cc9118", 1846 | "shasum": "" 1847 | }, 1848 | "require": { 1849 | "doctrine/instantiator": "^1.0.2", 1850 | "php": "^5.6 || ^7.0", 1851 | "phpunit/php-text-template": "^1.2", 1852 | "sebastian/exporter": "^1.2 || ^2.0" 1853 | }, 1854 | "conflict": { 1855 | "phpunit/phpunit": "<5.4.0" 1856 | }, 1857 | "require-dev": { 1858 | "phpunit/phpunit": "^5.4" 1859 | }, 1860 | "suggest": { 1861 | "ext-soap": "*" 1862 | }, 1863 | "type": "library", 1864 | "extra": { 1865 | "branch-alias": { 1866 | "dev-master": "3.2.x-dev" 1867 | } 1868 | }, 1869 | "autoload": { 1870 | "classmap": [ 1871 | "src/" 1872 | ] 1873 | }, 1874 | "notification-url": "https://packagist.org/downloads/", 1875 | "license": [ 1876 | "BSD-3-Clause" 1877 | ], 1878 | "authors": [ 1879 | { 1880 | "name": "Sebastian Bergmann", 1881 | "email": "sb@sebastian-bergmann.de", 1882 | "role": "lead" 1883 | } 1884 | ], 1885 | "description": "Mock Object library for PHPUnit", 1886 | "homepage": "https://github.com/sebastianbergmann/phpunit-mock-objects/", 1887 | "keywords": [ 1888 | "mock", 1889 | "xunit" 1890 | ], 1891 | "time": "2017-06-30T09:13:00+00:00" 1892 | }, 1893 | { 1894 | "name": "sebastian/code-unit-reverse-lookup", 1895 | "version": "1.0.1", 1896 | "source": { 1897 | "type": "git", 1898 | "url": "https://github.com/sebastianbergmann/code-unit-reverse-lookup.git", 1899 | "reference": "4419fcdb5eabb9caa61a27c7a1db532a6b55dd18" 1900 | }, 1901 | "dist": { 1902 | "type": "zip", 1903 | "url": "https://api.github.com/repos/sebastianbergmann/code-unit-reverse-lookup/zipball/4419fcdb5eabb9caa61a27c7a1db532a6b55dd18", 1904 | "reference": "4419fcdb5eabb9caa61a27c7a1db532a6b55dd18", 1905 | "shasum": "" 1906 | }, 1907 | "require": { 1908 | "php": "^5.6 || ^7.0" 1909 | }, 1910 | "require-dev": { 1911 | "phpunit/phpunit": "^5.7 || ^6.0" 1912 | }, 1913 | "type": "library", 1914 | "extra": { 1915 | "branch-alias": { 1916 | "dev-master": "1.0.x-dev" 1917 | } 1918 | }, 1919 | "autoload": { 1920 | "classmap": [ 1921 | "src/" 1922 | ] 1923 | }, 1924 | "notification-url": "https://packagist.org/downloads/", 1925 | "license": [ 1926 | "BSD-3-Clause" 1927 | ], 1928 | "authors": [ 1929 | { 1930 | "name": "Sebastian Bergmann", 1931 | "email": "sebastian@phpunit.de" 1932 | } 1933 | ], 1934 | "description": "Looks up which function or method a line of code belongs to", 1935 | "homepage": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/", 1936 | "time": "2017-03-04T06:30:41+00:00" 1937 | }, 1938 | { 1939 | "name": "sebastian/comparator", 1940 | "version": "1.2.4", 1941 | "source": { 1942 | "type": "git", 1943 | "url": "https://github.com/sebastianbergmann/comparator.git", 1944 | "reference": "2b7424b55f5047b47ac6e5ccb20b2aea4011d9be" 1945 | }, 1946 | "dist": { 1947 | "type": "zip", 1948 | "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/2b7424b55f5047b47ac6e5ccb20b2aea4011d9be", 1949 | "reference": "2b7424b55f5047b47ac6e5ccb20b2aea4011d9be", 1950 | "shasum": "" 1951 | }, 1952 | "require": { 1953 | "php": ">=5.3.3", 1954 | "sebastian/diff": "~1.2", 1955 | "sebastian/exporter": "~1.2 || ~2.0" 1956 | }, 1957 | "require-dev": { 1958 | "phpunit/phpunit": "~4.4" 1959 | }, 1960 | "type": "library", 1961 | "extra": { 1962 | "branch-alias": { 1963 | "dev-master": "1.2.x-dev" 1964 | } 1965 | }, 1966 | "autoload": { 1967 | "classmap": [ 1968 | "src/" 1969 | ] 1970 | }, 1971 | "notification-url": "https://packagist.org/downloads/", 1972 | "license": [ 1973 | "BSD-3-Clause" 1974 | ], 1975 | "authors": [ 1976 | { 1977 | "name": "Jeff Welch", 1978 | "email": "whatthejeff@gmail.com" 1979 | }, 1980 | { 1981 | "name": "Volker Dusch", 1982 | "email": "github@wallbash.com" 1983 | }, 1984 | { 1985 | "name": "Bernhard Schussek", 1986 | "email": "bschussek@2bepublished.at" 1987 | }, 1988 | { 1989 | "name": "Sebastian Bergmann", 1990 | "email": "sebastian@phpunit.de" 1991 | } 1992 | ], 1993 | "description": "Provides the functionality to compare PHP values for equality", 1994 | "homepage": "http://www.github.com/sebastianbergmann/comparator", 1995 | "keywords": [ 1996 | "comparator", 1997 | "compare", 1998 | "equality" 1999 | ], 2000 | "time": "2017-01-29T09:50:25+00:00" 2001 | }, 2002 | { 2003 | "name": "sebastian/diff", 2004 | "version": "1.4.3", 2005 | "source": { 2006 | "type": "git", 2007 | "url": "https://github.com/sebastianbergmann/diff.git", 2008 | "reference": "7f066a26a962dbe58ddea9f72a4e82874a3975a4" 2009 | }, 2010 | "dist": { 2011 | "type": "zip", 2012 | "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/7f066a26a962dbe58ddea9f72a4e82874a3975a4", 2013 | "reference": "7f066a26a962dbe58ddea9f72a4e82874a3975a4", 2014 | "shasum": "" 2015 | }, 2016 | "require": { 2017 | "php": "^5.3.3 || ^7.0" 2018 | }, 2019 | "require-dev": { 2020 | "phpunit/phpunit": "^4.8.35 || ^5.7 || ^6.0" 2021 | }, 2022 | "type": "library", 2023 | "extra": { 2024 | "branch-alias": { 2025 | "dev-master": "1.4-dev" 2026 | } 2027 | }, 2028 | "autoload": { 2029 | "classmap": [ 2030 | "src/" 2031 | ] 2032 | }, 2033 | "notification-url": "https://packagist.org/downloads/", 2034 | "license": [ 2035 | "BSD-3-Clause" 2036 | ], 2037 | "authors": [ 2038 | { 2039 | "name": "Kore Nordmann", 2040 | "email": "mail@kore-nordmann.de" 2041 | }, 2042 | { 2043 | "name": "Sebastian Bergmann", 2044 | "email": "sebastian@phpunit.de" 2045 | } 2046 | ], 2047 | "description": "Diff implementation", 2048 | "homepage": "https://github.com/sebastianbergmann/diff", 2049 | "keywords": [ 2050 | "diff" 2051 | ], 2052 | "time": "2017-05-22T07:24:03+00:00" 2053 | }, 2054 | { 2055 | "name": "sebastian/environment", 2056 | "version": "2.0.0", 2057 | "source": { 2058 | "type": "git", 2059 | "url": "https://github.com/sebastianbergmann/environment.git", 2060 | "reference": "5795ffe5dc5b02460c3e34222fee8cbe245d8fac" 2061 | }, 2062 | "dist": { 2063 | "type": "zip", 2064 | "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/5795ffe5dc5b02460c3e34222fee8cbe245d8fac", 2065 | "reference": "5795ffe5dc5b02460c3e34222fee8cbe245d8fac", 2066 | "shasum": "" 2067 | }, 2068 | "require": { 2069 | "php": "^5.6 || ^7.0" 2070 | }, 2071 | "require-dev": { 2072 | "phpunit/phpunit": "^5.0" 2073 | }, 2074 | "type": "library", 2075 | "extra": { 2076 | "branch-alias": { 2077 | "dev-master": "2.0.x-dev" 2078 | } 2079 | }, 2080 | "autoload": { 2081 | "classmap": [ 2082 | "src/" 2083 | ] 2084 | }, 2085 | "notification-url": "https://packagist.org/downloads/", 2086 | "license": [ 2087 | "BSD-3-Clause" 2088 | ], 2089 | "authors": [ 2090 | { 2091 | "name": "Sebastian Bergmann", 2092 | "email": "sebastian@phpunit.de" 2093 | } 2094 | ], 2095 | "description": "Provides functionality to handle HHVM/PHP environments", 2096 | "homepage": "http://www.github.com/sebastianbergmann/environment", 2097 | "keywords": [ 2098 | "Xdebug", 2099 | "environment", 2100 | "hhvm" 2101 | ], 2102 | "time": "2016-11-26T07:53:53+00:00" 2103 | }, 2104 | { 2105 | "name": "sebastian/exporter", 2106 | "version": "1.2.2", 2107 | "source": { 2108 | "type": "git", 2109 | "url": "https://github.com/sebastianbergmann/exporter.git", 2110 | "reference": "42c4c2eec485ee3e159ec9884f95b431287edde4" 2111 | }, 2112 | "dist": { 2113 | "type": "zip", 2114 | "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/42c4c2eec485ee3e159ec9884f95b431287edde4", 2115 | "reference": "42c4c2eec485ee3e159ec9884f95b431287edde4", 2116 | "shasum": "" 2117 | }, 2118 | "require": { 2119 | "php": ">=5.3.3", 2120 | "sebastian/recursion-context": "~1.0" 2121 | }, 2122 | "require-dev": { 2123 | "ext-mbstring": "*", 2124 | "phpunit/phpunit": "~4.4" 2125 | }, 2126 | "type": "library", 2127 | "extra": { 2128 | "branch-alias": { 2129 | "dev-master": "1.3.x-dev" 2130 | } 2131 | }, 2132 | "autoload": { 2133 | "classmap": [ 2134 | "src/" 2135 | ] 2136 | }, 2137 | "notification-url": "https://packagist.org/downloads/", 2138 | "license": [ 2139 | "BSD-3-Clause" 2140 | ], 2141 | "authors": [ 2142 | { 2143 | "name": "Jeff Welch", 2144 | "email": "whatthejeff@gmail.com" 2145 | }, 2146 | { 2147 | "name": "Volker Dusch", 2148 | "email": "github@wallbash.com" 2149 | }, 2150 | { 2151 | "name": "Bernhard Schussek", 2152 | "email": "bschussek@2bepublished.at" 2153 | }, 2154 | { 2155 | "name": "Sebastian Bergmann", 2156 | "email": "sebastian@phpunit.de" 2157 | }, 2158 | { 2159 | "name": "Adam Harvey", 2160 | "email": "aharvey@php.net" 2161 | } 2162 | ], 2163 | "description": "Provides the functionality to export PHP variables for visualization", 2164 | "homepage": "http://www.github.com/sebastianbergmann/exporter", 2165 | "keywords": [ 2166 | "export", 2167 | "exporter" 2168 | ], 2169 | "time": "2016-06-17T09:04:28+00:00" 2170 | }, 2171 | { 2172 | "name": "sebastian/global-state", 2173 | "version": "1.1.1", 2174 | "source": { 2175 | "type": "git", 2176 | "url": "https://github.com/sebastianbergmann/global-state.git", 2177 | "reference": "bc37d50fea7d017d3d340f230811c9f1d7280af4" 2178 | }, 2179 | "dist": { 2180 | "type": "zip", 2181 | "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/bc37d50fea7d017d3d340f230811c9f1d7280af4", 2182 | "reference": "bc37d50fea7d017d3d340f230811c9f1d7280af4", 2183 | "shasum": "" 2184 | }, 2185 | "require": { 2186 | "php": ">=5.3.3" 2187 | }, 2188 | "require-dev": { 2189 | "phpunit/phpunit": "~4.2" 2190 | }, 2191 | "suggest": { 2192 | "ext-uopz": "*" 2193 | }, 2194 | "type": "library", 2195 | "extra": { 2196 | "branch-alias": { 2197 | "dev-master": "1.0-dev" 2198 | } 2199 | }, 2200 | "autoload": { 2201 | "classmap": [ 2202 | "src/" 2203 | ] 2204 | }, 2205 | "notification-url": "https://packagist.org/downloads/", 2206 | "license": [ 2207 | "BSD-3-Clause" 2208 | ], 2209 | "authors": [ 2210 | { 2211 | "name": "Sebastian Bergmann", 2212 | "email": "sebastian@phpunit.de" 2213 | } 2214 | ], 2215 | "description": "Snapshotting of global state", 2216 | "homepage": "http://www.github.com/sebastianbergmann/global-state", 2217 | "keywords": [ 2218 | "global state" 2219 | ], 2220 | "time": "2015-10-12T03:26:01+00:00" 2221 | }, 2222 | { 2223 | "name": "sebastian/object-enumerator", 2224 | "version": "1.0.0", 2225 | "source": { 2226 | "type": "git", 2227 | "url": "https://github.com/sebastianbergmann/object-enumerator.git", 2228 | "reference": "d4ca2fb70344987502567bc50081c03e6192fb26" 2229 | }, 2230 | "dist": { 2231 | "type": "zip", 2232 | "url": "https://api.github.com/repos/sebastianbergmann/object-enumerator/zipball/d4ca2fb70344987502567bc50081c03e6192fb26", 2233 | "reference": "d4ca2fb70344987502567bc50081c03e6192fb26", 2234 | "shasum": "" 2235 | }, 2236 | "require": { 2237 | "php": ">=5.6", 2238 | "sebastian/recursion-context": "~1.0" 2239 | }, 2240 | "require-dev": { 2241 | "phpunit/phpunit": "~5" 2242 | }, 2243 | "type": "library", 2244 | "extra": { 2245 | "branch-alias": { 2246 | "dev-master": "1.0.x-dev" 2247 | } 2248 | }, 2249 | "autoload": { 2250 | "classmap": [ 2251 | "src/" 2252 | ] 2253 | }, 2254 | "notification-url": "https://packagist.org/downloads/", 2255 | "license": [ 2256 | "BSD-3-Clause" 2257 | ], 2258 | "authors": [ 2259 | { 2260 | "name": "Sebastian Bergmann", 2261 | "email": "sebastian@phpunit.de" 2262 | } 2263 | ], 2264 | "description": "Traverses array structures and object graphs to enumerate all referenced objects", 2265 | "homepage": "https://github.com/sebastianbergmann/object-enumerator/", 2266 | "time": "2016-01-28T13:25:10+00:00" 2267 | }, 2268 | { 2269 | "name": "sebastian/recursion-context", 2270 | "version": "1.0.5", 2271 | "source": { 2272 | "type": "git", 2273 | "url": "https://github.com/sebastianbergmann/recursion-context.git", 2274 | "reference": "b19cc3298482a335a95f3016d2f8a6950f0fbcd7" 2275 | }, 2276 | "dist": { 2277 | "type": "zip", 2278 | "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/b19cc3298482a335a95f3016d2f8a6950f0fbcd7", 2279 | "reference": "b19cc3298482a335a95f3016d2f8a6950f0fbcd7", 2280 | "shasum": "" 2281 | }, 2282 | "require": { 2283 | "php": ">=5.3.3" 2284 | }, 2285 | "require-dev": { 2286 | "phpunit/phpunit": "~4.4" 2287 | }, 2288 | "type": "library", 2289 | "extra": { 2290 | "branch-alias": { 2291 | "dev-master": "1.0.x-dev" 2292 | } 2293 | }, 2294 | "autoload": { 2295 | "classmap": [ 2296 | "src/" 2297 | ] 2298 | }, 2299 | "notification-url": "https://packagist.org/downloads/", 2300 | "license": [ 2301 | "BSD-3-Clause" 2302 | ], 2303 | "authors": [ 2304 | { 2305 | "name": "Jeff Welch", 2306 | "email": "whatthejeff@gmail.com" 2307 | }, 2308 | { 2309 | "name": "Sebastian Bergmann", 2310 | "email": "sebastian@phpunit.de" 2311 | }, 2312 | { 2313 | "name": "Adam Harvey", 2314 | "email": "aharvey@php.net" 2315 | } 2316 | ], 2317 | "description": "Provides functionality to recursively process PHP variables", 2318 | "homepage": "http://www.github.com/sebastianbergmann/recursion-context", 2319 | "time": "2016-10-03T07:41:43+00:00" 2320 | }, 2321 | { 2322 | "name": "sebastian/resource-operations", 2323 | "version": "1.0.0", 2324 | "source": { 2325 | "type": "git", 2326 | "url": "https://github.com/sebastianbergmann/resource-operations.git", 2327 | "reference": "ce990bb21759f94aeafd30209e8cfcdfa8bc3f52" 2328 | }, 2329 | "dist": { 2330 | "type": "zip", 2331 | "url": "https://api.github.com/repos/sebastianbergmann/resource-operations/zipball/ce990bb21759f94aeafd30209e8cfcdfa8bc3f52", 2332 | "reference": "ce990bb21759f94aeafd30209e8cfcdfa8bc3f52", 2333 | "shasum": "" 2334 | }, 2335 | "require": { 2336 | "php": ">=5.6.0" 2337 | }, 2338 | "type": "library", 2339 | "extra": { 2340 | "branch-alias": { 2341 | "dev-master": "1.0.x-dev" 2342 | } 2343 | }, 2344 | "autoload": { 2345 | "classmap": [ 2346 | "src/" 2347 | ] 2348 | }, 2349 | "notification-url": "https://packagist.org/downloads/", 2350 | "license": [ 2351 | "BSD-3-Clause" 2352 | ], 2353 | "authors": [ 2354 | { 2355 | "name": "Sebastian Bergmann", 2356 | "email": "sebastian@phpunit.de" 2357 | } 2358 | ], 2359 | "description": "Provides a list of PHP built-in functions that operate on resources", 2360 | "homepage": "https://www.github.com/sebastianbergmann/resource-operations", 2361 | "time": "2015-07-28T20:34:47+00:00" 2362 | }, 2363 | { 2364 | "name": "sebastian/version", 2365 | "version": "2.0.1", 2366 | "source": { 2367 | "type": "git", 2368 | "url": "https://github.com/sebastianbergmann/version.git", 2369 | "reference": "99732be0ddb3361e16ad77b68ba41efc8e979019" 2370 | }, 2371 | "dist": { 2372 | "type": "zip", 2373 | "url": "https://api.github.com/repos/sebastianbergmann/version/zipball/99732be0ddb3361e16ad77b68ba41efc8e979019", 2374 | "reference": "99732be0ddb3361e16ad77b68ba41efc8e979019", 2375 | "shasum": "" 2376 | }, 2377 | "require": { 2378 | "php": ">=5.6" 2379 | }, 2380 | "type": "library", 2381 | "extra": { 2382 | "branch-alias": { 2383 | "dev-master": "2.0.x-dev" 2384 | } 2385 | }, 2386 | "autoload": { 2387 | "classmap": [ 2388 | "src/" 2389 | ] 2390 | }, 2391 | "notification-url": "https://packagist.org/downloads/", 2392 | "license": [ 2393 | "BSD-3-Clause" 2394 | ], 2395 | "authors": [ 2396 | { 2397 | "name": "Sebastian Bergmann", 2398 | "email": "sebastian@phpunit.de", 2399 | "role": "lead" 2400 | } 2401 | ], 2402 | "description": "Library that helps with managing the version number of Git-hosted PHP projects", 2403 | "homepage": "https://github.com/sebastianbergmann/version", 2404 | "time": "2016-10-03T07:35:21+00:00" 2405 | }, 2406 | { 2407 | "name": "symfony/yaml", 2408 | "version": "v3.4.15", 2409 | "source": { 2410 | "type": "git", 2411 | "url": "https://github.com/symfony/yaml.git", 2412 | "reference": "c2f4812ead9f847cb69e90917ca7502e6892d6b8" 2413 | }, 2414 | "dist": { 2415 | "type": "zip", 2416 | "url": "https://api.github.com/repos/symfony/yaml/zipball/c2f4812ead9f847cb69e90917ca7502e6892d6b8", 2417 | "reference": "c2f4812ead9f847cb69e90917ca7502e6892d6b8", 2418 | "shasum": "" 2419 | }, 2420 | "require": { 2421 | "php": "^5.5.9|>=7.0.8", 2422 | "symfony/polyfill-ctype": "~1.8" 2423 | }, 2424 | "conflict": { 2425 | "symfony/console": "<3.4" 2426 | }, 2427 | "require-dev": { 2428 | "symfony/console": "~3.4|~4.0" 2429 | }, 2430 | "suggest": { 2431 | "symfony/console": "For validating YAML files using the lint command" 2432 | }, 2433 | "type": "library", 2434 | "extra": { 2435 | "branch-alias": { 2436 | "dev-master": "3.4-dev" 2437 | } 2438 | }, 2439 | "autoload": { 2440 | "psr-4": { 2441 | "Symfony\\Component\\Yaml\\": "" 2442 | }, 2443 | "exclude-from-classmap": [ 2444 | "/Tests/" 2445 | ] 2446 | }, 2447 | "notification-url": "https://packagist.org/downloads/", 2448 | "license": [ 2449 | "MIT" 2450 | ], 2451 | "authors": [ 2452 | { 2453 | "name": "Fabien Potencier", 2454 | "email": "fabien@symfony.com" 2455 | }, 2456 | { 2457 | "name": "Symfony Community", 2458 | "homepage": "https://symfony.com/contributors" 2459 | } 2460 | ], 2461 | "description": "Symfony Yaml Component", 2462 | "homepage": "https://symfony.com", 2463 | "time": "2018-08-10T07:34:36+00:00" 2464 | }, 2465 | { 2466 | "name": "webmozart/assert", 2467 | "version": "1.3.0", 2468 | "source": { 2469 | "type": "git", 2470 | "url": "https://github.com/webmozart/assert.git", 2471 | "reference": "0df1908962e7a3071564e857d86874dad1ef204a" 2472 | }, 2473 | "dist": { 2474 | "type": "zip", 2475 | "url": "https://api.github.com/repos/webmozart/assert/zipball/0df1908962e7a3071564e857d86874dad1ef204a", 2476 | "reference": "0df1908962e7a3071564e857d86874dad1ef204a", 2477 | "shasum": "" 2478 | }, 2479 | "require": { 2480 | "php": "^5.3.3 || ^7.0" 2481 | }, 2482 | "require-dev": { 2483 | "phpunit/phpunit": "^4.6", 2484 | "sebastian/version": "^1.0.1" 2485 | }, 2486 | "type": "library", 2487 | "extra": { 2488 | "branch-alias": { 2489 | "dev-master": "1.3-dev" 2490 | } 2491 | }, 2492 | "autoload": { 2493 | "psr-4": { 2494 | "Webmozart\\Assert\\": "src/" 2495 | } 2496 | }, 2497 | "notification-url": "https://packagist.org/downloads/", 2498 | "license": [ 2499 | "MIT" 2500 | ], 2501 | "authors": [ 2502 | { 2503 | "name": "Bernhard Schussek", 2504 | "email": "bschussek@gmail.com" 2505 | } 2506 | ], 2507 | "description": "Assertions to validate method input/output with nice error messages.", 2508 | "keywords": [ 2509 | "assert", 2510 | "check", 2511 | "validate" 2512 | ], 2513 | "time": "2018-01-29T19:49:41+00:00" 2514 | } 2515 | ], 2516 | "aliases": [], 2517 | "minimum-stability": "stable", 2518 | "stability-flags": [], 2519 | "prefer-stable": false, 2520 | "prefer-lowest": false, 2521 | "platform": { 2522 | "php": ">=5.6" 2523 | }, 2524 | "platform-dev": [] 2525 | } 2526 | --------------------------------------------------------------------------------