diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..547ee51
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,8 @@
+**/.idea/workspace.xml
+**/.idea/tasks.xml
+**/.idea/*.iws
+**/.idea/dataSources.local.xml
+**/.idea/dictionaries
+/vendor/
+.php_cs.cache
+/tests-report-html/
\ No newline at end of file
diff --git a/.idea/.gitignore b/.idea/.gitignore
new file mode 100644
index 0000000..0e40fe8
--- /dev/null
+++ b/.idea/.gitignore
@@ -0,0 +1,3 @@
+
+# Default ignored files
+/workspace.xml
\ No newline at end of file
diff --git a/.idea/atom-generator.iml b/.idea/atom-generator.iml
new file mode 100644
index 0000000..c956989
--- /dev/null
+++ b/.idea/atom-generator.iml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/composerJson.xml b/.idea/composerJson.xml
new file mode 100644
index 0000000..1b07430
--- /dev/null
+++ b/.idea/composerJson.xml
@@ -0,0 +1,10 @@
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/misc.xml b/.idea/misc.xml
new file mode 100644
index 0000000..28a804d
--- /dev/null
+++ b/.idea/misc.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/modules.xml b/.idea/modules.xml
new file mode 100644
index 0000000..516e8c5
--- /dev/null
+++ b/.idea/modules.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/php.xml b/.idea/php.xml
new file mode 100644
index 0000000..cf195ad
--- /dev/null
+++ b/.idea/php.xml
@@ -0,0 +1,9 @@
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/vcs.xml b/.idea/vcs.xml
new file mode 100644
index 0000000..94a25f7
--- /dev/null
+++ b/.idea/vcs.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.php_cs b/.php_cs
new file mode 100644
index 0000000..04a9c8e
--- /dev/null
+++ b/.php_cs
@@ -0,0 +1,20 @@
+exclude('vendor')
+ ->in(__DIR__)
+;
+
+return PhpCsFixer\Config::create()
+ ->setRules([
+ '@PSR1' => true,
+ '@PSR2' => true,
+ '@PhpCsFixer' => true,
+ '@PhpCsFixer:risky' => true,
+ 'array_syntax' => ['syntax' => 'short'],
+ 'php_unit_test_class_requires_covers' => false,
+ 'php_unit_test_case_static_method_calls' => ['call_type' => 'self'],
+ 'native_function_invocation' => false,
+ ])
+ ->setFinder($finder)
+ ;
\ No newline at end of file
diff --git a/.travis.yml b/.travis.yml
new file mode 100644
index 0000000..1488fc9
--- /dev/null
+++ b/.travis.yml
@@ -0,0 +1,16 @@
+language: php
+cache:
+ directories:
+ - $HOME/.composer
+sudo: false
+matrix:
+ fast_finish: true
+ include:
+ - php: '7.1'
+ - php: '7.2'
+ - php: '7.3'
+install:
+ - travis_retry composer install --no-progress --no-interaction --prefer-dist
+script:
+ - ./vendor/bin/php-cs-fixer fix --allow-risky=yes --dry-run -v --stop-on-violation
+ - composer phpunit
diff --git a/README.md b/README.md
index 36abe30..96b2011 100644
--- a/README.md
+++ b/README.md
@@ -1,2 +1,5 @@
+[](https://travis-ci.org/ddebin/atom-generator)
+
# atom-generator
+
Atom feed generator
diff --git a/composer.json b/composer.json
new file mode 100644
index 0000000..8f44f72
--- /dev/null
+++ b/composer.json
@@ -0,0 +1,45 @@
+{
+ "name": "ddebin/atom-generator",
+ "type": "library",
+ "description": "Atom feed generator",
+ "keywords": [
+ "atom",
+ "feed",
+ "generator"
+ ],
+ "homepage": "https://github.com/ddebin/atom-generator",
+ "license": "MIT",
+ "authors": [
+ {
+ "name": "Damien Debin",
+ "email": "damien.debin@gmail.com"
+ }
+ ],
+ "require": {
+ "php": "^7.1",
+ "webmozart/assert": "^1.5"
+ },
+ "require-dev": {
+ "friendsofphp/php-cs-fixer": "^2.15",
+ "phpunit/phpunit": "^7"
+ },
+ "config": {
+ "platform": {
+ "php": "7.1"
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "AtomGenerator\\": "src/"
+ }
+ },
+ "autoload-dev": {
+ "psr-4": {
+ "Tests\\": "tests"
+ }
+ },
+ "scripts": {
+ "test": "./vendor/bin/php-cs-fixer fix --allow-risky=yes && ./vendor/bin/phpunit",
+ "phpunit": "./vendor/bin/phpunit"
+ }
+}
diff --git a/composer.lock b/composer.lock
new file mode 100644
index 0000000..2b7750d
--- /dev/null
+++ b/composer.lock
@@ -0,0 +1,2574 @@
+{
+ "_readme": [
+ "This file locks the dependencies of your project to a known state",
+ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
+ "This file is @generated automatically"
+ ],
+ "content-hash": "204f5d457d0d4b09d3bdb0cc013933c9",
+ "packages": [
+ {
+ "name": "symfony/polyfill-ctype",
+ "version": "v1.12.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/symfony/polyfill-ctype.git",
+ "reference": "550ebaac289296ce228a706d0867afc34687e3f4"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/550ebaac289296ce228a706d0867afc34687e3f4",
+ "reference": "550ebaac289296ce228a706d0867afc34687e3f4",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=5.3.3"
+ },
+ "suggest": {
+ "ext-ctype": "For best performance"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "1.12-dev"
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "Symfony\\Polyfill\\Ctype\\": ""
+ },
+ "files": [
+ "bootstrap.php"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Gert de Pagter",
+ "email": "BackEndTea@gmail.com"
+ },
+ {
+ "name": "Symfony Community",
+ "homepage": "https://symfony.com/contributors"
+ }
+ ],
+ "description": "Symfony polyfill for ctype functions",
+ "homepage": "https://symfony.com",
+ "keywords": [
+ "compatibility",
+ "ctype",
+ "polyfill",
+ "portable"
+ ],
+ "time": "2019-08-06T08:03:45+00:00"
+ },
+ {
+ "name": "webmozart/assert",
+ "version": "1.5.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/webmozart/assert.git",
+ "reference": "88e6d84706d09a236046d686bbea96f07b3a34f4"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/webmozart/assert/zipball/88e6d84706d09a236046d686bbea96f07b3a34f4",
+ "reference": "88e6d84706d09a236046d686bbea96f07b3a34f4",
+ "shasum": ""
+ },
+ "require": {
+ "php": "^5.3.3 || ^7.0",
+ "symfony/polyfill-ctype": "^1.8"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "^4.8.36 || ^7.5.13"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "1.3-dev"
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "Webmozart\\Assert\\": "src/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Bernhard Schussek",
+ "email": "bschussek@gmail.com"
+ }
+ ],
+ "description": "Assertions to validate method input/output with nice error messages.",
+ "keywords": [
+ "assert",
+ "check",
+ "validate"
+ ],
+ "time": "2019-08-24T08:43:50+00:00"
+ }
+ ],
+ "packages-dev": [
+ {
+ "name": "composer/semver",
+ "version": "1.5.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/composer/semver.git",
+ "reference": "46d9139568ccb8d9e7cdd4539cab7347568a5e2e"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/composer/semver/zipball/46d9139568ccb8d9e7cdd4539cab7347568a5e2e",
+ "reference": "46d9139568ccb8d9e7cdd4539cab7347568a5e2e",
+ "shasum": ""
+ },
+ "require": {
+ "php": "^5.3.2 || ^7.0"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "^4.5 || ^5.0.5",
+ "phpunit/phpunit-mock-objects": "2.3.0 || ^3.0"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "1.x-dev"
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "Composer\\Semver\\": "src"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Nils Adermann",
+ "email": "naderman@naderman.de",
+ "homepage": "http://www.naderman.de"
+ },
+ {
+ "name": "Jordi Boggiano",
+ "email": "j.boggiano@seld.be",
+ "homepage": "http://seld.be"
+ },
+ {
+ "name": "Rob Bast",
+ "email": "rob.bast@gmail.com",
+ "homepage": "http://robbast.nl"
+ }
+ ],
+ "description": "Semver library that offers utilities, version constraint parsing and validation.",
+ "keywords": [
+ "semantic",
+ "semver",
+ "validation",
+ "versioning"
+ ],
+ "time": "2019-03-19T17:25:45+00:00"
+ },
+ {
+ "name": "composer/xdebug-handler",
+ "version": "1.3.3",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/composer/xdebug-handler.git",
+ "reference": "46867cbf8ca9fb8d60c506895449eb799db1184f"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/composer/xdebug-handler/zipball/46867cbf8ca9fb8d60c506895449eb799db1184f",
+ "reference": "46867cbf8ca9fb8d60c506895449eb799db1184f",
+ "shasum": ""
+ },
+ "require": {
+ "php": "^5.3.2 || ^7.0",
+ "psr/log": "^1.0"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "^4.8.35 || ^5.7 || ^6.5"
+ },
+ "type": "library",
+ "autoload": {
+ "psr-4": {
+ "Composer\\XdebugHandler\\": "src"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "John Stevenson",
+ "email": "john-stevenson@blueyonder.co.uk"
+ }
+ ],
+ "description": "Restarts a process without xdebug.",
+ "keywords": [
+ "Xdebug",
+ "performance"
+ ],
+ "time": "2019-05-27T17:52:04+00:00"
+ },
+ {
+ "name": "doctrine/annotations",
+ "version": "v1.7.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/doctrine/annotations.git",
+ "reference": "fa4c4e861e809d6a1103bd620cce63ed91aedfeb"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/doctrine/annotations/zipball/fa4c4e861e809d6a1103bd620cce63ed91aedfeb",
+ "reference": "fa4c4e861e809d6a1103bd620cce63ed91aedfeb",
+ "shasum": ""
+ },
+ "require": {
+ "doctrine/lexer": "1.*",
+ "php": "^7.1"
+ },
+ "require-dev": {
+ "doctrine/cache": "1.*",
+ "phpunit/phpunit": "^7.5@dev"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "1.7.x-dev"
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "Doctrine\\Common\\Annotations\\": "lib/Doctrine/Common/Annotations"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Guilherme Blanco",
+ "email": "guilhermeblanco@gmail.com"
+ },
+ {
+ "name": "Roman Borschel",
+ "email": "roman@code-factory.org"
+ },
+ {
+ "name": "Benjamin Eberlei",
+ "email": "kontakt@beberlei.de"
+ },
+ {
+ "name": "Jonathan Wage",
+ "email": "jonwage@gmail.com"
+ },
+ {
+ "name": "Johannes Schmitt",
+ "email": "schmittjoh@gmail.com"
+ }
+ ],
+ "description": "Docblock Annotations Parser",
+ "homepage": "http://www.doctrine-project.org",
+ "keywords": [
+ "annotations",
+ "docblock",
+ "parser"
+ ],
+ "time": "2019-08-08T18:11:40+00:00"
+ },
+ {
+ "name": "doctrine/instantiator",
+ "version": "1.2.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/doctrine/instantiator.git",
+ "reference": "a2c590166b2133a4633738648b6b064edae0814a"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/doctrine/instantiator/zipball/a2c590166b2133a4633738648b6b064edae0814a",
+ "reference": "a2c590166b2133a4633738648b6b064edae0814a",
+ "shasum": ""
+ },
+ "require": {
+ "php": "^7.1"
+ },
+ "require-dev": {
+ "doctrine/coding-standard": "^6.0",
+ "ext-pdo": "*",
+ "ext-phar": "*",
+ "phpbench/phpbench": "^0.13",
+ "phpstan/phpstan-phpunit": "^0.11",
+ "phpstan/phpstan-shim": "^0.11",
+ "phpunit/phpunit": "^7.0"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "1.2.x-dev"
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "Doctrine\\Instantiator\\": "src/Doctrine/Instantiator/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Marco Pivetta",
+ "email": "ocramius@gmail.com",
+ "homepage": "http://ocramius.github.com/"
+ }
+ ],
+ "description": "A small, lightweight utility to instantiate objects in PHP without invoking their constructors",
+ "homepage": "https://www.doctrine-project.org/projects/instantiator.html",
+ "keywords": [
+ "constructor",
+ "instantiate"
+ ],
+ "time": "2019-03-17T17:37:11+00:00"
+ },
+ {
+ "name": "doctrine/lexer",
+ "version": "1.0.2",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/doctrine/lexer.git",
+ "reference": "1febd6c3ef84253d7c815bed85fc622ad207a9f8"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/doctrine/lexer/zipball/1febd6c3ef84253d7c815bed85fc622ad207a9f8",
+ "reference": "1febd6c3ef84253d7c815bed85fc622ad207a9f8",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=5.3.2"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "^4.5"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "1.0.x-dev"
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "Doctrine\\Common\\Lexer\\": "lib/Doctrine/Common/Lexer"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Roman Borschel",
+ "email": "roman@code-factory.org"
+ },
+ {
+ "name": "Guilherme Blanco",
+ "email": "guilhermeblanco@gmail.com"
+ },
+ {
+ "name": "Johannes Schmitt",
+ "email": "schmittjoh@gmail.com"
+ }
+ ],
+ "description": "PHP Doctrine Lexer parser library that can be used in Top-Down, Recursive Descent Parsers.",
+ "homepage": "https://www.doctrine-project.org/projects/lexer.html",
+ "keywords": [
+ "annotations",
+ "docblock",
+ "lexer",
+ "parser",
+ "php"
+ ],
+ "time": "2019-06-08T11:03:04+00:00"
+ },
+ {
+ "name": "friendsofphp/php-cs-fixer",
+ "version": "v2.15.3",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/FriendsOfPHP/PHP-CS-Fixer.git",
+ "reference": "705490b0f282f21017d73561e9498d2b622ee34c"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/FriendsOfPHP/PHP-CS-Fixer/zipball/705490b0f282f21017d73561e9498d2b622ee34c",
+ "reference": "705490b0f282f21017d73561e9498d2b622ee34c",
+ "shasum": ""
+ },
+ "require": {
+ "composer/semver": "^1.4",
+ "composer/xdebug-handler": "^1.2",
+ "doctrine/annotations": "^1.2",
+ "ext-json": "*",
+ "ext-tokenizer": "*",
+ "php": "^5.6 || ^7.0",
+ "php-cs-fixer/diff": "^1.3",
+ "symfony/console": "^3.4.17 || ^4.1.6",
+ "symfony/event-dispatcher": "^3.0 || ^4.0",
+ "symfony/filesystem": "^3.0 || ^4.0",
+ "symfony/finder": "^3.0 || ^4.0",
+ "symfony/options-resolver": "^3.0 || ^4.0",
+ "symfony/polyfill-php70": "^1.0",
+ "symfony/polyfill-php72": "^1.4",
+ "symfony/process": "^3.0 || ^4.0",
+ "symfony/stopwatch": "^3.0 || ^4.0"
+ },
+ "require-dev": {
+ "johnkary/phpunit-speedtrap": "^1.1 || ^2.0 || ^3.0",
+ "justinrainbow/json-schema": "^5.0",
+ "keradus/cli-executor": "^1.2",
+ "mikey179/vfsstream": "^1.6",
+ "php-coveralls/php-coveralls": "^2.1",
+ "php-cs-fixer/accessible-object": "^1.0",
+ "php-cs-fixer/phpunit-constraint-isidenticalstring": "^1.1",
+ "php-cs-fixer/phpunit-constraint-xmlmatchesxsd": "^1.1",
+ "phpunit/phpunit": "^5.7.27 || ^6.5.14 || ^7.1",
+ "phpunitgoodpractices/traits": "^1.8",
+ "symfony/phpunit-bridge": "^4.3",
+ "symfony/yaml": "^3.0 || ^4.0"
+ },
+ "suggest": {
+ "ext-mbstring": "For handling non-UTF8 characters in cache signature.",
+ "php-cs-fixer/phpunit-constraint-isidenticalstring": "For IsIdenticalString constraint.",
+ "php-cs-fixer/phpunit-constraint-xmlmatchesxsd": "For XmlMatchesXsd constraint.",
+ "symfony/polyfill-mbstring": "When enabling `ext-mbstring` is not possible."
+ },
+ "bin": [
+ "php-cs-fixer"
+ ],
+ "type": "application",
+ "autoload": {
+ "psr-4": {
+ "PhpCsFixer\\": "src/"
+ },
+ "classmap": [
+ "tests/Test/AbstractFixerTestCase.php",
+ "tests/Test/AbstractIntegrationCaseFactory.php",
+ "tests/Test/AbstractIntegrationTestCase.php",
+ "tests/Test/Assert/AssertTokensTrait.php",
+ "tests/Test/IntegrationCase.php",
+ "tests/Test/IntegrationCaseFactory.php",
+ "tests/Test/IntegrationCaseFactoryInterface.php",
+ "tests/Test/InternalIntegrationCaseFactory.php",
+ "tests/TestCase.php"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Fabien Potencier",
+ "email": "fabien@symfony.com"
+ },
+ {
+ "name": "Dariusz Rumiński",
+ "email": "dariusz.ruminski@gmail.com"
+ }
+ ],
+ "description": "A tool to automatically fix PHP code style",
+ "time": "2019-08-31T12:51:54+00:00"
+ },
+ {
+ "name": "myclabs/deep-copy",
+ "version": "1.9.3",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/myclabs/DeepCopy.git",
+ "reference": "007c053ae6f31bba39dfa19a7726f56e9763bbea"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/007c053ae6f31bba39dfa19a7726f56e9763bbea",
+ "reference": "007c053ae6f31bba39dfa19a7726f56e9763bbea",
+ "shasum": ""
+ },
+ "require": {
+ "php": "^7.1"
+ },
+ "replace": {
+ "myclabs/deep-copy": "self.version"
+ },
+ "require-dev": {
+ "doctrine/collections": "^1.0",
+ "doctrine/common": "^2.6",
+ "phpunit/phpunit": "^7.1"
+ },
+ "type": "library",
+ "autoload": {
+ "psr-4": {
+ "DeepCopy\\": "src/DeepCopy/"
+ },
+ "files": [
+ "src/DeepCopy/deep_copy.php"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "description": "Create deep copies (clones) of your objects",
+ "keywords": [
+ "clone",
+ "copy",
+ "duplicate",
+ "object",
+ "object graph"
+ ],
+ "time": "2019-08-09T12:45:53+00:00"
+ },
+ {
+ "name": "paragonie/random_compat",
+ "version": "v9.99.99",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/paragonie/random_compat.git",
+ "reference": "84b4dfb120c6f9b4ff7b3685f9b8f1aa365a0c95"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/paragonie/random_compat/zipball/84b4dfb120c6f9b4ff7b3685f9b8f1aa365a0c95",
+ "reference": "84b4dfb120c6f9b4ff7b3685f9b8f1aa365a0c95",
+ "shasum": ""
+ },
+ "require": {
+ "php": "^7"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "4.*|5.*",
+ "vimeo/psalm": "^1"
+ },
+ "suggest": {
+ "ext-libsodium": "Provides a modern crypto API that can be used to generate random bytes."
+ },
+ "type": "library",
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Paragon Initiative Enterprises",
+ "email": "security@paragonie.com",
+ "homepage": "https://paragonie.com"
+ }
+ ],
+ "description": "PHP 5.x polyfill for random_bytes() and random_int() from PHP 7",
+ "keywords": [
+ "csprng",
+ "polyfill",
+ "pseudorandom",
+ "random"
+ ],
+ "time": "2018-07-02T15:55:56+00:00"
+ },
+ {
+ "name": "phar-io/manifest",
+ "version": "1.0.3",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/phar-io/manifest.git",
+ "reference": "7761fcacf03b4d4f16e7ccb606d4879ca431fcf4"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/phar-io/manifest/zipball/7761fcacf03b4d4f16e7ccb606d4879ca431fcf4",
+ "reference": "7761fcacf03b4d4f16e7ccb606d4879ca431fcf4",
+ "shasum": ""
+ },
+ "require": {
+ "ext-dom": "*",
+ "ext-phar": "*",
+ "phar-io/version": "^2.0",
+ "php": "^5.6 || ^7.0"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "1.0.x-dev"
+ }
+ },
+ "autoload": {
+ "classmap": [
+ "src/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "BSD-3-Clause"
+ ],
+ "authors": [
+ {
+ "name": "Arne Blankerts",
+ "email": "arne@blankerts.de",
+ "role": "Developer"
+ },
+ {
+ "name": "Sebastian Heuer",
+ "email": "sebastian@phpeople.de",
+ "role": "Developer"
+ },
+ {
+ "name": "Sebastian Bergmann",
+ "email": "sebastian@phpunit.de",
+ "role": "Developer"
+ }
+ ],
+ "description": "Component for reading phar.io manifest information from a PHP Archive (PHAR)",
+ "time": "2018-07-08T19:23:20+00:00"
+ },
+ {
+ "name": "phar-io/version",
+ "version": "2.0.1",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/phar-io/version.git",
+ "reference": "45a2ec53a73c70ce41d55cedef9063630abaf1b6"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/phar-io/version/zipball/45a2ec53a73c70ce41d55cedef9063630abaf1b6",
+ "reference": "45a2ec53a73c70ce41d55cedef9063630abaf1b6",
+ "shasum": ""
+ },
+ "require": {
+ "php": "^5.6 || ^7.0"
+ },
+ "type": "library",
+ "autoload": {
+ "classmap": [
+ "src/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "BSD-3-Clause"
+ ],
+ "authors": [
+ {
+ "name": "Arne Blankerts",
+ "email": "arne@blankerts.de",
+ "role": "Developer"
+ },
+ {
+ "name": "Sebastian Heuer",
+ "email": "sebastian@phpeople.de",
+ "role": "Developer"
+ },
+ {
+ "name": "Sebastian Bergmann",
+ "email": "sebastian@phpunit.de",
+ "role": "Developer"
+ }
+ ],
+ "description": "Library for handling version information and constraints",
+ "time": "2018-07-08T19:19:57+00:00"
+ },
+ {
+ "name": "php-cs-fixer/diff",
+ "version": "v1.3.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/PHP-CS-Fixer/diff.git",
+ "reference": "78bb099e9c16361126c86ce82ec4405ebab8e756"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/PHP-CS-Fixer/diff/zipball/78bb099e9c16361126c86ce82ec4405ebab8e756",
+ "reference": "78bb099e9c16361126c86ce82ec4405ebab8e756",
+ "shasum": ""
+ },
+ "require": {
+ "php": "^5.6 || ^7.0"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "^5.7.23 || ^6.4.3",
+ "symfony/process": "^3.3"
+ },
+ "type": "library",
+ "autoload": {
+ "classmap": [
+ "src/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "BSD-3-Clause"
+ ],
+ "authors": [
+ {
+ "name": "Kore Nordmann",
+ "email": "mail@kore-nordmann.de"
+ },
+ {
+ "name": "Sebastian Bergmann",
+ "email": "sebastian@phpunit.de"
+ },
+ {
+ "name": "SpacePossum"
+ }
+ ],
+ "description": "sebastian/diff v2 backport support for PHP5.6",
+ "homepage": "https://github.com/PHP-CS-Fixer",
+ "keywords": [
+ "diff"
+ ],
+ "time": "2018-02-15T16:58:55+00:00"
+ },
+ {
+ "name": "phpdocumentor/reflection-common",
+ "version": "2.0.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/phpDocumentor/ReflectionCommon.git",
+ "reference": "63a995caa1ca9e5590304cd845c15ad6d482a62a"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/phpDocumentor/ReflectionCommon/zipball/63a995caa1ca9e5590304cd845c15ad6d482a62a",
+ "reference": "63a995caa1ca9e5590304cd845c15ad6d482a62a",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=7.1"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "~6"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "2.x-dev"
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "phpDocumentor\\Reflection\\": "src/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Jaap van Otterdijk",
+ "email": "opensource@ijaap.nl"
+ }
+ ],
+ "description": "Common reflection classes used by phpdocumentor to reflect the code structure",
+ "homepage": "http://www.phpdoc.org",
+ "keywords": [
+ "FQSEN",
+ "phpDocumentor",
+ "phpdoc",
+ "reflection",
+ "static analysis"
+ ],
+ "time": "2018-08-07T13:53:10+00:00"
+ },
+ {
+ "name": "phpdocumentor/reflection-docblock",
+ "version": "4.3.2",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/phpDocumentor/ReflectionDocBlock.git",
+ "reference": "b83ff7cfcfee7827e1e78b637a5904fe6a96698e"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/b83ff7cfcfee7827e1e78b637a5904fe6a96698e",
+ "reference": "b83ff7cfcfee7827e1e78b637a5904fe6a96698e",
+ "shasum": ""
+ },
+ "require": {
+ "php": "^7.0",
+ "phpdocumentor/reflection-common": "^1.0.0 || ^2.0.0",
+ "phpdocumentor/type-resolver": "~0.4 || ^1.0.0",
+ "webmozart/assert": "^1.0"
+ },
+ "require-dev": {
+ "doctrine/instantiator": "^1.0.5",
+ "mockery/mockery": "^1.0",
+ "phpunit/phpunit": "^6.4"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "4.x-dev"
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "phpDocumentor\\Reflection\\": [
+ "src/"
+ ]
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Mike van Riel",
+ "email": "me@mikevanriel.com"
+ }
+ ],
+ "description": "With this component, a library can provide support for annotations via DocBlocks or otherwise retrieve information that is embedded in a DocBlock.",
+ "time": "2019-09-12T14:27:41+00:00"
+ },
+ {
+ "name": "phpdocumentor/type-resolver",
+ "version": "1.0.1",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/phpDocumentor/TypeResolver.git",
+ "reference": "2e32a6d48972b2c1976ed5d8967145b6cec4a4a9"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/phpDocumentor/TypeResolver/zipball/2e32a6d48972b2c1976ed5d8967145b6cec4a4a9",
+ "reference": "2e32a6d48972b2c1976ed5d8967145b6cec4a4a9",
+ "shasum": ""
+ },
+ "require": {
+ "php": "^7.1",
+ "phpdocumentor/reflection-common": "^2.0"
+ },
+ "require-dev": {
+ "ext-tokenizer": "^7.1",
+ "mockery/mockery": "~1",
+ "phpunit/phpunit": "^7.0"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "1.x-dev"
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "phpDocumentor\\Reflection\\": "src"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Mike van Riel",
+ "email": "me@mikevanriel.com"
+ }
+ ],
+ "description": "A PSR-5 based resolver of Class names, Types and Structural Element Names",
+ "time": "2019-08-22T18:11:29+00:00"
+ },
+ {
+ "name": "phpspec/prophecy",
+ "version": "1.8.1",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/phpspec/prophecy.git",
+ "reference": "1927e75f4ed19131ec9bcc3b002e07fb1173ee76"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/phpspec/prophecy/zipball/1927e75f4ed19131ec9bcc3b002e07fb1173ee76",
+ "reference": "1927e75f4ed19131ec9bcc3b002e07fb1173ee76",
+ "shasum": ""
+ },
+ "require": {
+ "doctrine/instantiator": "^1.0.2",
+ "php": "^5.3|^7.0",
+ "phpdocumentor/reflection-docblock": "^2.0|^3.0.2|^4.0",
+ "sebastian/comparator": "^1.1|^2.0|^3.0",
+ "sebastian/recursion-context": "^1.0|^2.0|^3.0"
+ },
+ "require-dev": {
+ "phpspec/phpspec": "^2.5|^3.2",
+ "phpunit/phpunit": "^4.8.35 || ^5.7 || ^6.5 || ^7.1"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "1.8.x-dev"
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "Prophecy\\": "src/Prophecy"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Konstantin Kudryashov",
+ "email": "ever.zet@gmail.com",
+ "homepage": "http://everzet.com"
+ },
+ {
+ "name": "Marcello Duarte",
+ "email": "marcello.duarte@gmail.com"
+ }
+ ],
+ "description": "Highly opinionated mocking framework for PHP 5.3+",
+ "homepage": "https://github.com/phpspec/prophecy",
+ "keywords": [
+ "Double",
+ "Dummy",
+ "fake",
+ "mock",
+ "spy",
+ "stub"
+ ],
+ "time": "2019-06-13T12:50:23+00:00"
+ },
+ {
+ "name": "phpunit/php-code-coverage",
+ "version": "6.1.4",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/sebastianbergmann/php-code-coverage.git",
+ "reference": "807e6013b00af69b6c5d9ceb4282d0393dbb9d8d"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/807e6013b00af69b6c5d9ceb4282d0393dbb9d8d",
+ "reference": "807e6013b00af69b6c5d9ceb4282d0393dbb9d8d",
+ "shasum": ""
+ },
+ "require": {
+ "ext-dom": "*",
+ "ext-xmlwriter": "*",
+ "php": "^7.1",
+ "phpunit/php-file-iterator": "^2.0",
+ "phpunit/php-text-template": "^1.2.1",
+ "phpunit/php-token-stream": "^3.0",
+ "sebastian/code-unit-reverse-lookup": "^1.0.1",
+ "sebastian/environment": "^3.1 || ^4.0",
+ "sebastian/version": "^2.0.1",
+ "theseer/tokenizer": "^1.1"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "^7.0"
+ },
+ "suggest": {
+ "ext-xdebug": "^2.6.0"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "6.1-dev"
+ }
+ },
+ "autoload": {
+ "classmap": [
+ "src/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "BSD-3-Clause"
+ ],
+ "authors": [
+ {
+ "name": "Sebastian Bergmann",
+ "email": "sebastian@phpunit.de",
+ "role": "lead"
+ }
+ ],
+ "description": "Library that provides collection, processing, and rendering functionality for PHP code coverage information.",
+ "homepage": "https://github.com/sebastianbergmann/php-code-coverage",
+ "keywords": [
+ "coverage",
+ "testing",
+ "xunit"
+ ],
+ "time": "2018-10-31T16:06:48+00:00"
+ },
+ {
+ "name": "phpunit/php-file-iterator",
+ "version": "2.0.2",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/sebastianbergmann/php-file-iterator.git",
+ "reference": "050bedf145a257b1ff02746c31894800e5122946"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/050bedf145a257b1ff02746c31894800e5122946",
+ "reference": "050bedf145a257b1ff02746c31894800e5122946",
+ "shasum": ""
+ },
+ "require": {
+ "php": "^7.1"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "^7.1"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "2.0.x-dev"
+ }
+ },
+ "autoload": {
+ "classmap": [
+ "src/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "BSD-3-Clause"
+ ],
+ "authors": [
+ {
+ "name": "Sebastian Bergmann",
+ "email": "sebastian@phpunit.de",
+ "role": "lead"
+ }
+ ],
+ "description": "FilterIterator implementation that filters files based on a list of suffixes.",
+ "homepage": "https://github.com/sebastianbergmann/php-file-iterator/",
+ "keywords": [
+ "filesystem",
+ "iterator"
+ ],
+ "time": "2018-09-13T20:33:42+00:00"
+ },
+ {
+ "name": "phpunit/php-text-template",
+ "version": "1.2.1",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/sebastianbergmann/php-text-template.git",
+ "reference": "31f8b717e51d9a2afca6c9f046f5d69fc27c8686"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/sebastianbergmann/php-text-template/zipball/31f8b717e51d9a2afca6c9f046f5d69fc27c8686",
+ "reference": "31f8b717e51d9a2afca6c9f046f5d69fc27c8686",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=5.3.3"
+ },
+ "type": "library",
+ "autoload": {
+ "classmap": [
+ "src/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "BSD-3-Clause"
+ ],
+ "authors": [
+ {
+ "name": "Sebastian Bergmann",
+ "email": "sebastian@phpunit.de",
+ "role": "lead"
+ }
+ ],
+ "description": "Simple template engine.",
+ "homepage": "https://github.com/sebastianbergmann/php-text-template/",
+ "keywords": [
+ "template"
+ ],
+ "time": "2015-06-21T13:50:34+00:00"
+ },
+ {
+ "name": "phpunit/php-timer",
+ "version": "2.1.2",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/sebastianbergmann/php-timer.git",
+ "reference": "1038454804406b0b5f5f520358e78c1c2f71501e"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/1038454804406b0b5f5f520358e78c1c2f71501e",
+ "reference": "1038454804406b0b5f5f520358e78c1c2f71501e",
+ "shasum": ""
+ },
+ "require": {
+ "php": "^7.1"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "^7.0"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "2.1-dev"
+ }
+ },
+ "autoload": {
+ "classmap": [
+ "src/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "BSD-3-Clause"
+ ],
+ "authors": [
+ {
+ "name": "Sebastian Bergmann",
+ "email": "sebastian@phpunit.de",
+ "role": "lead"
+ }
+ ],
+ "description": "Utility class for timing",
+ "homepage": "https://github.com/sebastianbergmann/php-timer/",
+ "keywords": [
+ "timer"
+ ],
+ "time": "2019-06-07T04:22:29+00:00"
+ },
+ {
+ "name": "phpunit/php-token-stream",
+ "version": "3.1.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/sebastianbergmann/php-token-stream.git",
+ "reference": "e899757bb3df5ff6e95089132f32cd59aac2220a"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/sebastianbergmann/php-token-stream/zipball/e899757bb3df5ff6e95089132f32cd59aac2220a",
+ "reference": "e899757bb3df5ff6e95089132f32cd59aac2220a",
+ "shasum": ""
+ },
+ "require": {
+ "ext-tokenizer": "*",
+ "php": "^7.1"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "^7.0"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "3.1-dev"
+ }
+ },
+ "autoload": {
+ "classmap": [
+ "src/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "BSD-3-Clause"
+ ],
+ "authors": [
+ {
+ "name": "Sebastian Bergmann",
+ "email": "sebastian@phpunit.de"
+ }
+ ],
+ "description": "Wrapper around PHP's tokenizer extension.",
+ "homepage": "https://github.com/sebastianbergmann/php-token-stream/",
+ "keywords": [
+ "tokenizer"
+ ],
+ "time": "2019-07-25T05:29:42+00:00"
+ },
+ {
+ "name": "phpunit/phpunit",
+ "version": "7.5.15",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/sebastianbergmann/phpunit.git",
+ "reference": "d79c053d972856b8b941bb233e39dc521a5093f0"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/d79c053d972856b8b941bb233e39dc521a5093f0",
+ "reference": "d79c053d972856b8b941bb233e39dc521a5093f0",
+ "shasum": ""
+ },
+ "require": {
+ "doctrine/instantiator": "^1.1",
+ "ext-dom": "*",
+ "ext-json": "*",
+ "ext-libxml": "*",
+ "ext-mbstring": "*",
+ "ext-xml": "*",
+ "myclabs/deep-copy": "^1.7",
+ "phar-io/manifest": "^1.0.2",
+ "phar-io/version": "^2.0",
+ "php": "^7.1",
+ "phpspec/prophecy": "^1.7",
+ "phpunit/php-code-coverage": "^6.0.7",
+ "phpunit/php-file-iterator": "^2.0.1",
+ "phpunit/php-text-template": "^1.2.1",
+ "phpunit/php-timer": "^2.1",
+ "sebastian/comparator": "^3.0",
+ "sebastian/diff": "^3.0",
+ "sebastian/environment": "^4.0",
+ "sebastian/exporter": "^3.1",
+ "sebastian/global-state": "^2.0",
+ "sebastian/object-enumerator": "^3.0.3",
+ "sebastian/resource-operations": "^2.0",
+ "sebastian/version": "^2.0.1"
+ },
+ "conflict": {
+ "phpunit/phpunit-mock-objects": "*"
+ },
+ "require-dev": {
+ "ext-pdo": "*"
+ },
+ "suggest": {
+ "ext-soap": "*",
+ "ext-xdebug": "*",
+ "phpunit/php-invoker": "^2.0"
+ },
+ "bin": [
+ "phpunit"
+ ],
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "7.5-dev"
+ }
+ },
+ "autoload": {
+ "classmap": [
+ "src/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "BSD-3-Clause"
+ ],
+ "authors": [
+ {
+ "name": "Sebastian Bergmann",
+ "email": "sebastian@phpunit.de",
+ "role": "lead"
+ }
+ ],
+ "description": "The PHP Unit Testing framework.",
+ "homepage": "https://phpunit.de/",
+ "keywords": [
+ "phpunit",
+ "testing",
+ "xunit"
+ ],
+ "time": "2019-08-21T07:05:16+00:00"
+ },
+ {
+ "name": "psr/log",
+ "version": "1.1.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/php-fig/log.git",
+ "reference": "6c001f1daafa3a3ac1d8ff69ee4db8e799a654dd"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/php-fig/log/zipball/6c001f1daafa3a3ac1d8ff69ee4db8e799a654dd",
+ "reference": "6c001f1daafa3a3ac1d8ff69ee4db8e799a654dd",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=5.3.0"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "1.0.x-dev"
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "Psr\\Log\\": "Psr/Log/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "PHP-FIG",
+ "homepage": "http://www.php-fig.org/"
+ }
+ ],
+ "description": "Common interface for logging libraries",
+ "homepage": "https://github.com/php-fig/log",
+ "keywords": [
+ "log",
+ "psr",
+ "psr-3"
+ ],
+ "time": "2018-11-20T15:27:04+00:00"
+ },
+ {
+ "name": "sebastian/code-unit-reverse-lookup",
+ "version": "1.0.1",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/sebastianbergmann/code-unit-reverse-lookup.git",
+ "reference": "4419fcdb5eabb9caa61a27c7a1db532a6b55dd18"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/sebastianbergmann/code-unit-reverse-lookup/zipball/4419fcdb5eabb9caa61a27c7a1db532a6b55dd18",
+ "reference": "4419fcdb5eabb9caa61a27c7a1db532a6b55dd18",
+ "shasum": ""
+ },
+ "require": {
+ "php": "^5.6 || ^7.0"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "^5.7 || ^6.0"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "1.0.x-dev"
+ }
+ },
+ "autoload": {
+ "classmap": [
+ "src/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "BSD-3-Clause"
+ ],
+ "authors": [
+ {
+ "name": "Sebastian Bergmann",
+ "email": "sebastian@phpunit.de"
+ }
+ ],
+ "description": "Looks up which function or method a line of code belongs to",
+ "homepage": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/",
+ "time": "2017-03-04T06:30:41+00:00"
+ },
+ {
+ "name": "sebastian/comparator",
+ "version": "3.0.2",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/sebastianbergmann/comparator.git",
+ "reference": "5de4fc177adf9bce8df98d8d141a7559d7ccf6da"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/5de4fc177adf9bce8df98d8d141a7559d7ccf6da",
+ "reference": "5de4fc177adf9bce8df98d8d141a7559d7ccf6da",
+ "shasum": ""
+ },
+ "require": {
+ "php": "^7.1",
+ "sebastian/diff": "^3.0",
+ "sebastian/exporter": "^3.1"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "^7.1"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "3.0-dev"
+ }
+ },
+ "autoload": {
+ "classmap": [
+ "src/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "BSD-3-Clause"
+ ],
+ "authors": [
+ {
+ "name": "Jeff Welch",
+ "email": "whatthejeff@gmail.com"
+ },
+ {
+ "name": "Volker Dusch",
+ "email": "github@wallbash.com"
+ },
+ {
+ "name": "Bernhard Schussek",
+ "email": "bschussek@2bepublished.at"
+ },
+ {
+ "name": "Sebastian Bergmann",
+ "email": "sebastian@phpunit.de"
+ }
+ ],
+ "description": "Provides the functionality to compare PHP values for equality",
+ "homepage": "https://github.com/sebastianbergmann/comparator",
+ "keywords": [
+ "comparator",
+ "compare",
+ "equality"
+ ],
+ "time": "2018-07-12T15:12:46+00:00"
+ },
+ {
+ "name": "sebastian/diff",
+ "version": "3.0.2",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/sebastianbergmann/diff.git",
+ "reference": "720fcc7e9b5cf384ea68d9d930d480907a0c1a29"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/720fcc7e9b5cf384ea68d9d930d480907a0c1a29",
+ "reference": "720fcc7e9b5cf384ea68d9d930d480907a0c1a29",
+ "shasum": ""
+ },
+ "require": {
+ "php": "^7.1"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "^7.5 || ^8.0",
+ "symfony/process": "^2 || ^3.3 || ^4"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "3.0-dev"
+ }
+ },
+ "autoload": {
+ "classmap": [
+ "src/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "BSD-3-Clause"
+ ],
+ "authors": [
+ {
+ "name": "Kore Nordmann",
+ "email": "mail@kore-nordmann.de"
+ },
+ {
+ "name": "Sebastian Bergmann",
+ "email": "sebastian@phpunit.de"
+ }
+ ],
+ "description": "Diff implementation",
+ "homepage": "https://github.com/sebastianbergmann/diff",
+ "keywords": [
+ "diff",
+ "udiff",
+ "unidiff",
+ "unified diff"
+ ],
+ "time": "2019-02-04T06:01:07+00:00"
+ },
+ {
+ "name": "sebastian/environment",
+ "version": "4.2.2",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/sebastianbergmann/environment.git",
+ "reference": "f2a2c8e1c97c11ace607a7a667d73d47c19fe404"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/f2a2c8e1c97c11ace607a7a667d73d47c19fe404",
+ "reference": "f2a2c8e1c97c11ace607a7a667d73d47c19fe404",
+ "shasum": ""
+ },
+ "require": {
+ "php": "^7.1"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "^7.5"
+ },
+ "suggest": {
+ "ext-posix": "*"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "4.2-dev"
+ }
+ },
+ "autoload": {
+ "classmap": [
+ "src/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "BSD-3-Clause"
+ ],
+ "authors": [
+ {
+ "name": "Sebastian Bergmann",
+ "email": "sebastian@phpunit.de"
+ }
+ ],
+ "description": "Provides functionality to handle HHVM/PHP environments",
+ "homepage": "http://www.github.com/sebastianbergmann/environment",
+ "keywords": [
+ "Xdebug",
+ "environment",
+ "hhvm"
+ ],
+ "time": "2019-05-05T09:05:15+00:00"
+ },
+ {
+ "name": "sebastian/exporter",
+ "version": "3.1.1",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/sebastianbergmann/exporter.git",
+ "reference": "06a9a5947f47b3029d76118eb5c22802e5869687"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/06a9a5947f47b3029d76118eb5c22802e5869687",
+ "reference": "06a9a5947f47b3029d76118eb5c22802e5869687",
+ "shasum": ""
+ },
+ "require": {
+ "php": "^7.0",
+ "sebastian/recursion-context": "^3.0"
+ },
+ "require-dev": {
+ "ext-mbstring": "*",
+ "phpunit/phpunit": "^6.0"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "3.1.x-dev"
+ }
+ },
+ "autoload": {
+ "classmap": [
+ "src/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "BSD-3-Clause"
+ ],
+ "authors": [
+ {
+ "name": "Sebastian Bergmann",
+ "email": "sebastian@phpunit.de"
+ },
+ {
+ "name": "Jeff Welch",
+ "email": "whatthejeff@gmail.com"
+ },
+ {
+ "name": "Volker Dusch",
+ "email": "github@wallbash.com"
+ },
+ {
+ "name": "Adam Harvey",
+ "email": "aharvey@php.net"
+ },
+ {
+ "name": "Bernhard Schussek",
+ "email": "bschussek@gmail.com"
+ }
+ ],
+ "description": "Provides the functionality to export PHP variables for visualization",
+ "homepage": "http://www.github.com/sebastianbergmann/exporter",
+ "keywords": [
+ "export",
+ "exporter"
+ ],
+ "time": "2019-08-11T12:43:14+00:00"
+ },
+ {
+ "name": "sebastian/global-state",
+ "version": "2.0.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/sebastianbergmann/global-state.git",
+ "reference": "e8ba02eed7bbbb9e59e43dedd3dddeff4a56b0c4"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/e8ba02eed7bbbb9e59e43dedd3dddeff4a56b0c4",
+ "reference": "e8ba02eed7bbbb9e59e43dedd3dddeff4a56b0c4",
+ "shasum": ""
+ },
+ "require": {
+ "php": "^7.0"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "^6.0"
+ },
+ "suggest": {
+ "ext-uopz": "*"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "2.0-dev"
+ }
+ },
+ "autoload": {
+ "classmap": [
+ "src/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "BSD-3-Clause"
+ ],
+ "authors": [
+ {
+ "name": "Sebastian Bergmann",
+ "email": "sebastian@phpunit.de"
+ }
+ ],
+ "description": "Snapshotting of global state",
+ "homepage": "http://www.github.com/sebastianbergmann/global-state",
+ "keywords": [
+ "global state"
+ ],
+ "time": "2017-04-27T15:39:26+00:00"
+ },
+ {
+ "name": "sebastian/object-enumerator",
+ "version": "3.0.3",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/sebastianbergmann/object-enumerator.git",
+ "reference": "7cfd9e65d11ffb5af41198476395774d4c8a84c5"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/sebastianbergmann/object-enumerator/zipball/7cfd9e65d11ffb5af41198476395774d4c8a84c5",
+ "reference": "7cfd9e65d11ffb5af41198476395774d4c8a84c5",
+ "shasum": ""
+ },
+ "require": {
+ "php": "^7.0",
+ "sebastian/object-reflector": "^1.1.1",
+ "sebastian/recursion-context": "^3.0"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "^6.0"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "3.0.x-dev"
+ }
+ },
+ "autoload": {
+ "classmap": [
+ "src/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "BSD-3-Clause"
+ ],
+ "authors": [
+ {
+ "name": "Sebastian Bergmann",
+ "email": "sebastian@phpunit.de"
+ }
+ ],
+ "description": "Traverses array structures and object graphs to enumerate all referenced objects",
+ "homepage": "https://github.com/sebastianbergmann/object-enumerator/",
+ "time": "2017-08-03T12:35:26+00:00"
+ },
+ {
+ "name": "sebastian/object-reflector",
+ "version": "1.1.1",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/sebastianbergmann/object-reflector.git",
+ "reference": "773f97c67f28de00d397be301821b06708fca0be"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/sebastianbergmann/object-reflector/zipball/773f97c67f28de00d397be301821b06708fca0be",
+ "reference": "773f97c67f28de00d397be301821b06708fca0be",
+ "shasum": ""
+ },
+ "require": {
+ "php": "^7.0"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "^6.0"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "1.1-dev"
+ }
+ },
+ "autoload": {
+ "classmap": [
+ "src/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "BSD-3-Clause"
+ ],
+ "authors": [
+ {
+ "name": "Sebastian Bergmann",
+ "email": "sebastian@phpunit.de"
+ }
+ ],
+ "description": "Allows reflection of object attributes, including inherited and non-public ones",
+ "homepage": "https://github.com/sebastianbergmann/object-reflector/",
+ "time": "2017-03-29T09:07:27+00:00"
+ },
+ {
+ "name": "sebastian/recursion-context",
+ "version": "3.0.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/sebastianbergmann/recursion-context.git",
+ "reference": "5b0cd723502bac3b006cbf3dbf7a1e3fcefe4fa8"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/5b0cd723502bac3b006cbf3dbf7a1e3fcefe4fa8",
+ "reference": "5b0cd723502bac3b006cbf3dbf7a1e3fcefe4fa8",
+ "shasum": ""
+ },
+ "require": {
+ "php": "^7.0"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "^6.0"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "3.0.x-dev"
+ }
+ },
+ "autoload": {
+ "classmap": [
+ "src/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "BSD-3-Clause"
+ ],
+ "authors": [
+ {
+ "name": "Jeff Welch",
+ "email": "whatthejeff@gmail.com"
+ },
+ {
+ "name": "Sebastian Bergmann",
+ "email": "sebastian@phpunit.de"
+ },
+ {
+ "name": "Adam Harvey",
+ "email": "aharvey@php.net"
+ }
+ ],
+ "description": "Provides functionality to recursively process PHP variables",
+ "homepage": "http://www.github.com/sebastianbergmann/recursion-context",
+ "time": "2017-03-03T06:23:57+00:00"
+ },
+ {
+ "name": "sebastian/resource-operations",
+ "version": "2.0.1",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/sebastianbergmann/resource-operations.git",
+ "reference": "4d7a795d35b889bf80a0cc04e08d77cedfa917a9"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/sebastianbergmann/resource-operations/zipball/4d7a795d35b889bf80a0cc04e08d77cedfa917a9",
+ "reference": "4d7a795d35b889bf80a0cc04e08d77cedfa917a9",
+ "shasum": ""
+ },
+ "require": {
+ "php": "^7.1"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "2.0-dev"
+ }
+ },
+ "autoload": {
+ "classmap": [
+ "src/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "BSD-3-Clause"
+ ],
+ "authors": [
+ {
+ "name": "Sebastian Bergmann",
+ "email": "sebastian@phpunit.de"
+ }
+ ],
+ "description": "Provides a list of PHP built-in functions that operate on resources",
+ "homepage": "https://www.github.com/sebastianbergmann/resource-operations",
+ "time": "2018-10-04T04:07:39+00:00"
+ },
+ {
+ "name": "sebastian/version",
+ "version": "2.0.1",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/sebastianbergmann/version.git",
+ "reference": "99732be0ddb3361e16ad77b68ba41efc8e979019"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/sebastianbergmann/version/zipball/99732be0ddb3361e16ad77b68ba41efc8e979019",
+ "reference": "99732be0ddb3361e16ad77b68ba41efc8e979019",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=5.6"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "2.0.x-dev"
+ }
+ },
+ "autoload": {
+ "classmap": [
+ "src/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "BSD-3-Clause"
+ ],
+ "authors": [
+ {
+ "name": "Sebastian Bergmann",
+ "email": "sebastian@phpunit.de",
+ "role": "lead"
+ }
+ ],
+ "description": "Library that helps with managing the version number of Git-hosted PHP projects",
+ "homepage": "https://github.com/sebastianbergmann/version",
+ "time": "2016-10-03T07:35:21+00:00"
+ },
+ {
+ "name": "symfony/console",
+ "version": "v3.4.31",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/symfony/console.git",
+ "reference": "4510f04e70344d70952566e4262a0b11df39cb10"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/symfony/console/zipball/4510f04e70344d70952566e4262a0b11df39cb10",
+ "reference": "4510f04e70344d70952566e4262a0b11df39cb10",
+ "shasum": ""
+ },
+ "require": {
+ "php": "^5.5.9|>=7.0.8",
+ "symfony/debug": "~2.8|~3.0|~4.0",
+ "symfony/polyfill-mbstring": "~1.0"
+ },
+ "conflict": {
+ "symfony/dependency-injection": "<3.4",
+ "symfony/process": "<3.3"
+ },
+ "provide": {
+ "psr/log-implementation": "1.0"
+ },
+ "require-dev": {
+ "psr/log": "~1.0",
+ "symfony/config": "~3.3|~4.0",
+ "symfony/dependency-injection": "~3.4|~4.0",
+ "symfony/event-dispatcher": "~2.8|~3.0|~4.0",
+ "symfony/lock": "~3.4|~4.0",
+ "symfony/process": "~3.3|~4.0"
+ },
+ "suggest": {
+ "psr/log": "For using the console logger",
+ "symfony/event-dispatcher": "",
+ "symfony/lock": "",
+ "symfony/process": ""
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "3.4-dev"
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "Symfony\\Component\\Console\\": ""
+ },
+ "exclude-from-classmap": [
+ "/Tests/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Fabien Potencier",
+ "email": "fabien@symfony.com"
+ },
+ {
+ "name": "Symfony Community",
+ "homepage": "https://symfony.com/contributors"
+ }
+ ],
+ "description": "Symfony Console Component",
+ "homepage": "https://symfony.com",
+ "time": "2019-08-26T07:52:58+00:00"
+ },
+ {
+ "name": "symfony/debug",
+ "version": "v3.4.31",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/symfony/debug.git",
+ "reference": "0b600300918780001e2821db77bc28b677794486"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/symfony/debug/zipball/0b600300918780001e2821db77bc28b677794486",
+ "reference": "0b600300918780001e2821db77bc28b677794486",
+ "shasum": ""
+ },
+ "require": {
+ "php": "^5.5.9|>=7.0.8",
+ "psr/log": "~1.0"
+ },
+ "conflict": {
+ "symfony/http-kernel": ">=2.3,<2.3.24|~2.4.0|>=2.5,<2.5.9|>=2.6,<2.6.2"
+ },
+ "require-dev": {
+ "symfony/http-kernel": "~2.8|~3.0|~4.0"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "3.4-dev"
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "Symfony\\Component\\Debug\\": ""
+ },
+ "exclude-from-classmap": [
+ "/Tests/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Fabien Potencier",
+ "email": "fabien@symfony.com"
+ },
+ {
+ "name": "Symfony Community",
+ "homepage": "https://symfony.com/contributors"
+ }
+ ],
+ "description": "Symfony Debug Component",
+ "homepage": "https://symfony.com",
+ "time": "2019-08-20T13:31:17+00:00"
+ },
+ {
+ "name": "symfony/event-dispatcher",
+ "version": "v3.4.31",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/symfony/event-dispatcher.git",
+ "reference": "3e922c4c3430b9de624e8a285dada5e61e230959"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/3e922c4c3430b9de624e8a285dada5e61e230959",
+ "reference": "3e922c4c3430b9de624e8a285dada5e61e230959",
+ "shasum": ""
+ },
+ "require": {
+ "php": "^5.5.9|>=7.0.8"
+ },
+ "conflict": {
+ "symfony/dependency-injection": "<3.3"
+ },
+ "require-dev": {
+ "psr/log": "~1.0",
+ "symfony/config": "~2.8|~3.0|~4.0",
+ "symfony/dependency-injection": "~3.3|~4.0",
+ "symfony/expression-language": "~2.8|~3.0|~4.0",
+ "symfony/stopwatch": "~2.8|~3.0|~4.0"
+ },
+ "suggest": {
+ "symfony/dependency-injection": "",
+ "symfony/http-kernel": ""
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "3.4-dev"
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "Symfony\\Component\\EventDispatcher\\": ""
+ },
+ "exclude-from-classmap": [
+ "/Tests/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Fabien Potencier",
+ "email": "fabien@symfony.com"
+ },
+ {
+ "name": "Symfony Community",
+ "homepage": "https://symfony.com/contributors"
+ }
+ ],
+ "description": "Symfony EventDispatcher Component",
+ "homepage": "https://symfony.com",
+ "time": "2019-08-23T08:05:57+00:00"
+ },
+ {
+ "name": "symfony/filesystem",
+ "version": "v3.4.31",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/symfony/filesystem.git",
+ "reference": "00e3a6ddd723b8bcfe4f2a1b6f82b98eeeb51516"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/symfony/filesystem/zipball/00e3a6ddd723b8bcfe4f2a1b6f82b98eeeb51516",
+ "reference": "00e3a6ddd723b8bcfe4f2a1b6f82b98eeeb51516",
+ "shasum": ""
+ },
+ "require": {
+ "php": "^5.5.9|>=7.0.8",
+ "symfony/polyfill-ctype": "~1.8"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "3.4-dev"
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "Symfony\\Component\\Filesystem\\": ""
+ },
+ "exclude-from-classmap": [
+ "/Tests/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Fabien Potencier",
+ "email": "fabien@symfony.com"
+ },
+ {
+ "name": "Symfony Community",
+ "homepage": "https://symfony.com/contributors"
+ }
+ ],
+ "description": "Symfony Filesystem Component",
+ "homepage": "https://symfony.com",
+ "time": "2019-08-20T13:31:17+00:00"
+ },
+ {
+ "name": "symfony/finder",
+ "version": "v3.4.31",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/symfony/finder.git",
+ "reference": "1fcad80b440abcd1451767349906b6f9d3961d37"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/symfony/finder/zipball/1fcad80b440abcd1451767349906b6f9d3961d37",
+ "reference": "1fcad80b440abcd1451767349906b6f9d3961d37",
+ "shasum": ""
+ },
+ "require": {
+ "php": "^5.5.9|>=7.0.8"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "3.4-dev"
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "Symfony\\Component\\Finder\\": ""
+ },
+ "exclude-from-classmap": [
+ "/Tests/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Fabien Potencier",
+ "email": "fabien@symfony.com"
+ },
+ {
+ "name": "Symfony Community",
+ "homepage": "https://symfony.com/contributors"
+ }
+ ],
+ "description": "Symfony Finder Component",
+ "homepage": "https://symfony.com",
+ "time": "2019-08-14T09:39:58+00:00"
+ },
+ {
+ "name": "symfony/options-resolver",
+ "version": "v3.4.31",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/symfony/options-resolver.git",
+ "reference": "a7c00586a9ef70acf0f17085e51c399bf9620e03"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/symfony/options-resolver/zipball/a7c00586a9ef70acf0f17085e51c399bf9620e03",
+ "reference": "a7c00586a9ef70acf0f17085e51c399bf9620e03",
+ "shasum": ""
+ },
+ "require": {
+ "php": "^5.5.9|>=7.0.8"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "3.4-dev"
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "Symfony\\Component\\OptionsResolver\\": ""
+ },
+ "exclude-from-classmap": [
+ "/Tests/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Fabien Potencier",
+ "email": "fabien@symfony.com"
+ },
+ {
+ "name": "Symfony Community",
+ "homepage": "https://symfony.com/contributors"
+ }
+ ],
+ "description": "Symfony OptionsResolver Component",
+ "homepage": "https://symfony.com",
+ "keywords": [
+ "config",
+ "configuration",
+ "options"
+ ],
+ "time": "2019-08-03T21:15:25+00:00"
+ },
+ {
+ "name": "symfony/polyfill-mbstring",
+ "version": "v1.12.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/symfony/polyfill-mbstring.git",
+ "reference": "b42a2f66e8f1b15ccf25652c3424265923eb4f17"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/b42a2f66e8f1b15ccf25652c3424265923eb4f17",
+ "reference": "b42a2f66e8f1b15ccf25652c3424265923eb4f17",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=5.3.3"
+ },
+ "suggest": {
+ "ext-mbstring": "For best performance"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "1.12-dev"
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "Symfony\\Polyfill\\Mbstring\\": ""
+ },
+ "files": [
+ "bootstrap.php"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Nicolas Grekas",
+ "email": "p@tchwork.com"
+ },
+ {
+ "name": "Symfony Community",
+ "homepage": "https://symfony.com/contributors"
+ }
+ ],
+ "description": "Symfony polyfill for the Mbstring extension",
+ "homepage": "https://symfony.com",
+ "keywords": [
+ "compatibility",
+ "mbstring",
+ "polyfill",
+ "portable",
+ "shim"
+ ],
+ "time": "2019-08-06T08:03:45+00:00"
+ },
+ {
+ "name": "symfony/polyfill-php70",
+ "version": "v1.12.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/symfony/polyfill-php70.git",
+ "reference": "54b4c428a0054e254223797d2713c31e08610831"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/symfony/polyfill-php70/zipball/54b4c428a0054e254223797d2713c31e08610831",
+ "reference": "54b4c428a0054e254223797d2713c31e08610831",
+ "shasum": ""
+ },
+ "require": {
+ "paragonie/random_compat": "~1.0|~2.0|~9.99",
+ "php": ">=5.3.3"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "1.12-dev"
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "Symfony\\Polyfill\\Php70\\": ""
+ },
+ "files": [
+ "bootstrap.php"
+ ],
+ "classmap": [
+ "Resources/stubs"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Nicolas Grekas",
+ "email": "p@tchwork.com"
+ },
+ {
+ "name": "Symfony Community",
+ "homepage": "https://symfony.com/contributors"
+ }
+ ],
+ "description": "Symfony polyfill backporting some PHP 7.0+ features to lower PHP versions",
+ "homepage": "https://symfony.com",
+ "keywords": [
+ "compatibility",
+ "polyfill",
+ "portable",
+ "shim"
+ ],
+ "time": "2019-08-06T08:03:45+00:00"
+ },
+ {
+ "name": "symfony/polyfill-php72",
+ "version": "v1.12.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/symfony/polyfill-php72.git",
+ "reference": "04ce3335667451138df4307d6a9b61565560199e"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/symfony/polyfill-php72/zipball/04ce3335667451138df4307d6a9b61565560199e",
+ "reference": "04ce3335667451138df4307d6a9b61565560199e",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=5.3.3"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "1.12-dev"
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "Symfony\\Polyfill\\Php72\\": ""
+ },
+ "files": [
+ "bootstrap.php"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Nicolas Grekas",
+ "email": "p@tchwork.com"
+ },
+ {
+ "name": "Symfony Community",
+ "homepage": "https://symfony.com/contributors"
+ }
+ ],
+ "description": "Symfony polyfill backporting some PHP 7.2+ features to lower PHP versions",
+ "homepage": "https://symfony.com",
+ "keywords": [
+ "compatibility",
+ "polyfill",
+ "portable",
+ "shim"
+ ],
+ "time": "2019-08-06T08:03:45+00:00"
+ },
+ {
+ "name": "symfony/process",
+ "version": "v3.4.31",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/symfony/process.git",
+ "reference": "d822cb654000a95b7855362c0d5b127f6a6d8baa"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/symfony/process/zipball/d822cb654000a95b7855362c0d5b127f6a6d8baa",
+ "reference": "d822cb654000a95b7855362c0d5b127f6a6d8baa",
+ "shasum": ""
+ },
+ "require": {
+ "php": "^5.5.9|>=7.0.8"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "3.4-dev"
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "Symfony\\Component\\Process\\": ""
+ },
+ "exclude-from-classmap": [
+ "/Tests/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Fabien Potencier",
+ "email": "fabien@symfony.com"
+ },
+ {
+ "name": "Symfony Community",
+ "homepage": "https://symfony.com/contributors"
+ }
+ ],
+ "description": "Symfony Process Component",
+ "homepage": "https://symfony.com",
+ "time": "2019-08-26T07:52:58+00:00"
+ },
+ {
+ "name": "symfony/stopwatch",
+ "version": "v3.4.31",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/symfony/stopwatch.git",
+ "reference": "c0c27e38f8accb452f830a4ec8e8ac94b6ec864a"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/symfony/stopwatch/zipball/c0c27e38f8accb452f830a4ec8e8ac94b6ec864a",
+ "reference": "c0c27e38f8accb452f830a4ec8e8ac94b6ec864a",
+ "shasum": ""
+ },
+ "require": {
+ "php": "^5.5.9|>=7.0.8"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "3.4-dev"
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "Symfony\\Component\\Stopwatch\\": ""
+ },
+ "exclude-from-classmap": [
+ "/Tests/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Fabien Potencier",
+ "email": "fabien@symfony.com"
+ },
+ {
+ "name": "Symfony Community",
+ "homepage": "https://symfony.com/contributors"
+ }
+ ],
+ "description": "Symfony Stopwatch Component",
+ "homepage": "https://symfony.com",
+ "time": "2019-08-06T13:24:37+00:00"
+ },
+ {
+ "name": "theseer/tokenizer",
+ "version": "1.1.3",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/theseer/tokenizer.git",
+ "reference": "11336f6f84e16a720dae9d8e6ed5019efa85a0f9"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/theseer/tokenizer/zipball/11336f6f84e16a720dae9d8e6ed5019efa85a0f9",
+ "reference": "11336f6f84e16a720dae9d8e6ed5019efa85a0f9",
+ "shasum": ""
+ },
+ "require": {
+ "ext-dom": "*",
+ "ext-tokenizer": "*",
+ "ext-xmlwriter": "*",
+ "php": "^7.0"
+ },
+ "type": "library",
+ "autoload": {
+ "classmap": [
+ "src/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "BSD-3-Clause"
+ ],
+ "authors": [
+ {
+ "name": "Arne Blankerts",
+ "role": "Developer",
+ "email": "arne@blankerts.de"
+ }
+ ],
+ "description": "A small library for converting tokenized PHP source code into XML and potentially other formats",
+ "time": "2019-06-13T22:48:21+00:00"
+ }
+ ],
+ "aliases": [],
+ "minimum-stability": "stable",
+ "stability-flags": [],
+ "prefer-stable": false,
+ "prefer-lowest": false,
+ "platform": {
+ "php": "^7.1"
+ },
+ "platform-dev": [],
+ "platform-overrides": {
+ "php": "7.1"
+ }
+}
diff --git a/phpunit.xml b/phpunit.xml
new file mode 100644
index 0000000..a28d686
--- /dev/null
+++ b/phpunit.xml
@@ -0,0 +1,17 @@
+
+
+
+
+ tests
+
+
+
+
+ src
+ tests
+
+
+
\ No newline at end of file
diff --git a/src/AbstractElement.php b/src/AbstractElement.php
new file mode 100644
index 0000000..9f85807
--- /dev/null
+++ b/src/AbstractElement.php
@@ -0,0 +1,288 @@
+setTitle('Example, Inc.');
+ $this->setId('http://example.com/');
+ $this->setUpdatedDateTime(new DateTime('now'));
+ }
+
+ /**
+ * @param string $id
+ */
+ public function setId(string $id): void
+ {
+ if ((0 !== strpos($id, 'tag:')) && (false === filter_var($id, FILTER_VALIDATE_URL))) {
+ throw new InvalidArgumentException('Expected a value to be a valid URI/tag. Got '.$id);
+ }
+ $this->id = $id;
+ }
+
+ /**
+ * @param string $title
+ * @param null|string $type
+ */
+ public function setTitle(string $title, ?string $type = null): void
+ {
+ Assert::oneOf($type, [null, 'text', 'xhtml', 'html']);
+ $this->title = $title;
+ $this->titleType = $type;
+ }
+
+ /**
+ * @param DateTimeInterface $updated
+ */
+ public function setUpdatedDateTime(DateTimeInterface $updated): void
+ {
+ $this->updateDateTime = $updated;
+ }
+
+ /**
+ * @param null|string $rights
+ * @param null|string $type
+ */
+ public function setRights(?string $rights, ?string $type = null): void
+ {
+ Assert::true((null !== $rights) || (null === $type));
+ Assert::oneOf($type, [null, 'text', 'xhtml', 'html']);
+ $this->rights = $rights;
+ $this->rightsType = $type;
+ }
+
+ /**
+ * @param string $term
+ * @param null|string $scheme
+ * @param null|string $label
+ */
+ public function addCategory(string $term, ?string $scheme = null, ?string $label = null): void
+ {
+ $category = [
+ 'term' => $term,
+ ];
+
+ if (null !== $scheme) {
+ self::assertURL($scheme);
+ $category['scheme'] = $scheme;
+ }
+
+ if (null !== $label) {
+ $category['label'] = $label;
+ }
+
+ $this->categories[] = $category;
+ }
+
+ /**
+ * @param string $url
+ * @param null|string $rel
+ * @param null|string $type
+ * @param null|string $hreflang
+ * @param null|string $title
+ */
+ public function addLink(string $url, ?string $rel = null, ?string $type = null, ?string $hreflang = null, ?string $title = null): void
+ {
+ self::assertURL($url);
+
+ $link = [
+ 'href' => $url,
+ ];
+
+ if (null !== $rel) {
+ Assert::oneOf($rel, [null, 'alternate', 'enclosure', 'related', 'self', 'via', 'payment']);
+ $link['rel'] = $rel;
+ }
+
+ if (null !== $type) {
+ $link['type'] = $type;
+ }
+
+ if (null !== $hreflang) {
+ $link['hreflang'] = $hreflang;
+ }
+
+ if (null !== $title) {
+ $link['title'] = $title;
+ }
+
+ $this->links[] = $link;
+ }
+
+ /**
+ * @param string $name
+ * @param null|string $email
+ * @param null|string $uri
+ */
+ public function addAuthor(string $name, ?string $email = null, ?string $uri = null): void
+ {
+ $this->authors[] = self::createPerson($name, $email, $uri);
+ }
+
+ /**
+ * @param string $name
+ * @param null|string $email
+ * @param null|string $uri
+ */
+ public function addContributor(string $name, ?string $email = null, ?string $uri = null): void
+ {
+ $this->contributors[] = self::createPerson($name, $email, $uri);
+ }
+
+ /**
+ * @param SimpleXMLElement $parent
+ */
+ public function addChildrenTo(SimpleXMLElement $parent): void
+ {
+ $parent->addChild('id', $this->id);
+
+ self::addChildWithTypeToElement($parent, 'title', $this->title, $this->titleType);
+
+ $parent->addChild('updated', $this->updateDateTime->format(DATE_ATOM));
+
+ if (null !== $this->rights) {
+ self::addChildWithTypeToElement($parent, 'rights', $this->rights, $this->rightsType);
+ }
+
+ foreach ([
+ 'category' => $this->categories,
+ 'link' => $this->links,
+ ] as $type => $elements) {
+ foreach ($elements as $element) {
+ $child = $parent->addChild($type);
+ foreach ($element as $name => $attribute) {
+ $child->addAttribute($name, $attribute);
+ }
+ }
+ }
+
+ foreach ([
+ 'author' => $this->authors,
+ 'contributor' => $this->contributors,
+ ] as $type => $elements) {
+ foreach ($elements as $element) {
+ $child = $parent->addChild($type);
+ foreach ($element as $name => $attribute) {
+ $child->addChild($name, $attribute);
+ }
+ }
+ }
+ }
+
+ /**
+ * @param string $name
+ * @param null|string $email
+ * @param null|string $uri
+ *
+ * @return mixed[]
+ */
+ protected static function createPerson(string $name, ?string $email = null, ?string $uri = null): array
+ {
+ $person = [
+ 'name' => $name,
+ ];
+
+ if (null !== $email) {
+ Assert::email($email);
+ $person['email'] = $email;
+ }
+
+ if (null !== $uri) {
+ self::assertURL($uri);
+ $person['uri'] = $uri;
+ }
+
+ return $person;
+ }
+
+ /**
+ * @param SimpleXMLElement $parent
+ * @param string $name
+ * @param null|string $data
+ * @param null|string $type
+ *
+ * @return SimpleXMLElement
+ */
+ protected static function addChildWithTypeToElement(SimpleXMLElement $parent, string $name, ?string $data, ?string $type): SimpleXMLElement
+ {
+ if (null !== $data) {
+ if (in_array($type, ['html', 'xhtml'], true)) {
+ $element = $parent->addChild($name);
+ self::addCData($data, $element);
+ } else {
+ $element = $parent->addChild($name, $data);
+ }
+ } else {
+ $element = $parent->addChild($name);
+ }
+ if (null !== $type) {
+ $element->addAttribute('type', $type);
+ }
+
+ return $element;
+ }
+
+ /**
+ * @param string $cdataText
+ * @param SimpleXMLElement $element
+ */
+ protected static function addCData(string $cdataText, SimpleXMLElement $element): void
+ {
+ $node = dom_import_simplexml($element);
+ Assert::isInstanceOf($node, DOMElement::class);
+ $no = $node->ownerDocument;
+ $node->appendChild($no->createCDATASection($cdataText));
+ }
+
+ /**
+ * @param string $value
+ */
+ protected static function assertURL(string $value): void
+ {
+ if (false === filter_var($value, FILTER_VALIDATE_URL)) {
+ throw new InvalidArgumentException('Expected a value to be a valid URI. Got '.$value);
+ }
+ }
+}
diff --git a/src/Entry.php b/src/Entry.php
new file mode 100644
index 0000000..c6fe634
--- /dev/null
+++ b/src/Entry.php
@@ -0,0 +1,76 @@
+summary = $summary;
+ $this->summaryType = $type;
+ }
+
+ /**
+ * @param null|string $content
+ * @param null|string $type
+ * @param null|string $src
+ */
+ public function setContent(?string $content, ?string $type = null, ?string $src = null): void
+ {
+ Assert::true(((null !== $content) && (null === $src)) ||
+ ((null === $content) && (null !== $src)) ||
+ ((null === $content) && (null === $src) && (null === $type)));
+ Assert::oneOf($type, [null, 'text', 'xhtml', 'html']);
+ if (null !== $src) {
+ self::assertURL($src);
+ }
+ $this->content = $content;
+ $this->contentType = $type;
+ $this->contentSrc = $src;
+ }
+
+ /**
+ * @param SimpleXMLElement $parent
+ */
+ public function addChildrenTo(SimpleXMLElement $parent): void
+ {
+ $entry = $parent->addChild('entry');
+
+ parent::addChildrenTo($entry);
+
+ if (null !== $this->summary) {
+ self::addChildWithTypeToElement($entry, 'summary', $this->summary, $this->summaryType);
+ }
+ if (null !== $this->content) {
+ self::addChildWithTypeToElement($entry, 'content', $this->content, $this->contentType);
+ }
+ if (null !== $this->contentSrc) {
+ $content = self::addChildWithTypeToElement($entry, 'content', null, $this->contentType);
+ $content->addAttribute('src', $this->contentSrc);
+ }
+ }
+}
diff --git a/src/Feed.php b/src/Feed.php
new file mode 100644
index 0000000..a88951b
--- /dev/null
+++ b/src/Feed.php
@@ -0,0 +1,254 @@
+setPrettify(true);
+ }
+
+ /**
+ * @param bool $prettify
+ */
+ public function setPrettify(bool $prettify): void
+ {
+ $this->prettify = $prettify;
+ }
+
+ /**
+ * @param null|string $language
+ */
+ public function setLanguage(?string $language): void
+ {
+ $this->language = $language;
+ }
+
+ /**
+ * @param null|string $subtitle
+ */
+ public function setSubtitle(?string $subtitle): void
+ {
+ $this->subtitle = $subtitle;
+ }
+
+ /**
+ * @param null|string $uri
+ */
+ public function setIconUri(?string $uri): void
+ {
+ if (null !== $uri) {
+ self::assertURL($uri);
+ }
+ $this->icon = $uri;
+ }
+
+ /**
+ * @param null|string $uri
+ */
+ public function setLogoUri(?string $uri): void
+ {
+ if (null !== $uri) {
+ self::assertURL($uri);
+ }
+ $this->logo = $uri;
+ }
+
+ /**
+ * @param null|string $generator
+ * @param null|string $uri
+ * @param null|string $version
+ */
+ public function setGenerator(?string $generator, ?string $uri = null, ?string $version = null): void
+ {
+ Assert::true((null !== $generator) || ((null === $uri) && (null === $version)));
+
+ $this->generator = $generator;
+ $this->generatorVersion = $version;
+
+ if (null !== $uri) {
+ self::assertURL($uri);
+ $this->generatorUri = $uri;
+ }
+ }
+
+ /**
+ * @param Entry $entry
+ */
+ public function addEntry(Entry $entry): void
+ {
+ $this->entries[] = $entry;
+ }
+
+ /**
+ * @param string $ns
+ * @param string $url
+ * @param string $name
+ * @param mixed $value
+ * @param null|string[] $attributes
+ */
+ public function addCustomElement(string $ns, string $url, string $name, $value, ?array $attributes = null): void
+ {
+ self::assertURL($url);
+
+ $this->customElements[] = [
+ 'ns' => $ns,
+ 'url' => $url,
+ 'name' => $name,
+ 'value' => $value,
+ 'attributes' => $attributes ?? [],
+ ];
+ }
+
+ /**
+ * @param SimpleXMLElement $parent
+ */
+ public function addChildrenTo(SimpleXMLElement $parent): void
+ {
+ parent::addChildrenTo($parent);
+
+ if (null !== $this->subtitle) {
+ $parent->addChild('subtitle', $this->subtitle);
+ }
+
+ if (null !== $this->logo) {
+ $parent->addChild('logo', $this->logo);
+ }
+
+ if (null !== $this->icon) {
+ $parent->addChild('icon', $this->icon);
+ }
+
+ if (null !== $this->generator) {
+ $generator = $parent->addChild('generator', $this->generator);
+ if (null !== $this->generatorVersion) {
+ $generator->addAttribute('version', $this->generatorVersion);
+ }
+ if (null !== $this->generatorUri) {
+ $generator->addAttribute('uri', $this->generatorUri);
+ }
+ }
+
+ foreach ($this->customElements as $customElement) {
+ $element = $parent->addChild($customElement['name'], $customElement['value'], $customElement['ns']);
+ foreach ($customElement['attributes'] as $name => $value) {
+ $element->addAttribute($name, $value);
+ }
+ }
+
+ foreach ($this->entries as $entry) {
+ $entry->addChildrenTo($parent);
+ }
+ }
+
+ /**
+ * @return SimpleXMLElement
+ */
+ public function getSimpleXML(): SimpleXMLElement
+ {
+ $attributes = [];
+ if (null !== $this->language) {
+ $attributes['xml:lang'] = $this->language;
+ }
+ foreach ($this->customElements as $customElement) {
+ $attributes['xmlns:'.$customElement['ns']] = $customElement['url'];
+ }
+
+ $attributesString = '';
+ foreach ($attributes as $name => $attribute) {
+ $attributesString .= " {$name}=\"{$attribute}\"";
+ }
+
+ $xml = new SimpleXMLElement('');
+
+ $this->addChildrenTo($xml);
+
+ return $xml;
+ }
+
+ /**
+ * @return DOMDocument
+ */
+ public function getDocument(): DOMDocument
+ {
+ $node = dom_import_simplexml($this->getSimpleXML());
+ Assert::isInstanceOf($node, DOMElement::class);
+
+ return $node->ownerDocument;
+ }
+
+ /**
+ * @return string
+ */
+ public function saveXML(): string
+ {
+ $dom = $this->getDocument();
+ $dom->preserveWhiteSpace = !$this->prettify;
+ $dom->formatOutput = $this->prettify;
+
+ return $dom->saveXML();
+ }
+
+ /**
+ * Validate XML DOMDocument against ATOM NRG schema.
+ * NRG schema coming from https://validator.w3.org/feed/docs/rfc4287.html#schema.
+ *
+ * @see https://cweiske.de/tagebuch/atom-validation.htm
+ *
+ * @param DOMDocument $document
+ * @param null|libXMLError[] $errors
+ *
+ * @return bool
+ */
+ public static function validateFeed(DOMDocument $document, ?array &$errors = null): bool
+ {
+ libxml_use_internal_errors(true);
+ $valid = $document->relaxNGValidate(__DIR__.'/atom.rng');
+ $errors = libxml_get_errors();
+ libxml_clear_errors();
+
+ return $valid;
+ }
+}
diff --git a/src/atom.rng b/src/atom.rng
new file mode 100644
index 0000000..f1407fc
--- /dev/null
+++ b/src/atom.rng
@@ -0,0 +1,598 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ text
+ html
+
+
+
+
+
+
+
+
+ xhtml
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ An atom:feed must have an atom:author unless all of its atom:entry children have an atom:author.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ An atom:entry must have at least one atom:link element with a rel attribute of 'alternate' or an atom:content.
+
+
+ An atom:entry must have an atom:author if its feed does not.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ text
+ html
+
+
+
+
+
+
+
+
+
+
+
+
+ xhtml
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 1
+ [^:]*
+
+
+
+
+
+ .+/.+
+
+
+
+
+
+ [A-Za-z]{1,8}(-[A-Za-z0-9]{1,8})*
+
+
+
+
+
+
+
+
+
+ .+@.+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ xml:base
+ xml:lang
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/tests/FeedTest.php b/tests/FeedTest.php
new file mode 100644
index 0000000..87ea1cd
--- /dev/null
+++ b/tests/FeedTest.php
@@ -0,0 +1,185 @@
+setTitle('title');
+ $feed->addAuthor('author', 'author@test.com', 'http://test.com/author');
+ $feed->addAuthor('author', 'author@test.com', 'http://test.com/author');
+ $feed->setRights('©'.date('Y'));
+ $feed->addLink('http://test.com/link', 'via', 'text/html');
+ $feed->addCategory('term', 'http://scheme.com', 'label');
+ $feed->setId('tag:test');
+ $feed->setLanguage('en');
+ $feed->setIconUri('http://test.com/icon');
+ $feed->setLogoUri('http://test.com/logo');
+ $feed->setSubtitle('subtitle');
+ $feed->setGenerator('generator', 'http://test.com/generator', 'version');
+ $feed->addContributor('contributor', 'contributor@test.com', 'http://test.com/contributor');
+ $feed->setUpdatedDateTime(new DateTime('2019-05-04T20:00:40Z'));
+ $feed->addCustomElement('sy', 'http://purl.org/rss/1.0/modules/syndication', 'updatePeriod', 'hourly');
+ $feed->addCustomElement('sy', 'http://purl.org/rss/1.0/modules/syndication', 'sy:updateFrequency', 10);
+
+ $entry = new Entry();
+ $entry->setTitle('entry title', 'text');
+ $entry->setSummary('entry summary', 'text');
+ $entry->setSummary('entry summary', 'text');
+ $entry->setId('tag:entry-test');
+ $entry->setRights('©'.date('Y'));
+ $entry->addAuthor('author', 'test@test.com', 'http://test.com/author');
+ $entry->addCategory('term', 'ftp://scheme.org', 'label');
+ $entry->addContributor('contributor', 'contributor@test.com', 'http://test.com/contributor');
+ $entry->addLink('http://test.com/alternate_entry', 'alternate', 'text/html', 'en', 'alternate_entry');
+ $entry->setContent('Entry content & ...', 'html');
+ $entry->setUpdatedDateTime(new DateTime('2019-05-04T21:00:40Z'));
+
+ $feed->addEntry($entry);
+
+ if (self::$reset) {
+ file_put_contents(self::TEST_FEED_XML_PATH_1, $feed->saveXML()); // @codeCoverageIgnore
+ }
+
+ $valid = Feed::validateFeed($feed->getDocument(), $errors);
+ self::assertTrue($valid, self::formatXmlErrors($errors));
+
+ self::assertStringEqualsFile(self::TEST_FEED_XML_PATH_1, $feed->saveXML());
+ }
+
+ /**
+ * @group buildXML
+ */
+ public function testFeedCreation2(): void
+ {
+ $feed = new Feed();
+ $feed->setPrettify(false);
+ $feed->setTitle('title');
+ $feed->setId('tag:test');
+ $feed->setGenerator(null);
+ $feed->setUpdatedDateTime(new DateTime('2019-05-04T20:00:40Z'));
+
+ $entry = new Entry();
+ $entry->setTitle('entry title', 'html');
+ $entry->setSummary('entry summary', 'text');
+ $entry->setSummary(null);
+ $entry->setId('tag:entry-test');
+ $entry->setRights(null);
+ $entry->setContent(null, null, 'http://test.com/content');
+ $entry->setUpdatedDateTime(new DateTime('2019-05-04T21:00:40Z'));
+
+ $feed->addEntry($entry);
+
+ if (self::$reset) {
+ file_put_contents(self::TEST_FEED_XML_PATH_2, $feed->saveXML()); // @codeCoverageIgnore
+ }
+
+ $valid = Feed::validateFeed($feed->getDocument(), $errors);
+ self::assertTrue($valid, self::formatXmlErrors($errors));
+
+ self::assertStringEqualsFile(self::TEST_FEED_XML_PATH_2, $feed->saveXML());
+ }
+
+ /**
+ * @group buildXML
+ */
+ public function testFeedCreation3(): void
+ {
+ $feed = new Feed();
+ $feed->setTitle('title');
+ $feed->setId('tag:test');
+ $feed->setUpdatedDateTime(new DateTime('2019-05-04T20:00:40Z'));
+
+ $entry = new Entry();
+ $entry->setTitle('entry title', 'html');
+ $entry->setId('tag:entry-test');
+ $entry->setContent(null);
+ $entry->setUpdatedDateTime(new DateTime('2019-05-04T21:00:40Z'));
+
+ $feed->addEntry($entry);
+
+ if (self::$reset) {
+ file_put_contents(self::TEST_FEED_XML_PATH_3, $feed->saveXML()); // @codeCoverageIgnore
+ }
+
+ $valid = Feed::validateFeed($feed->getDocument(), $errors);
+ self::assertTrue($valid, self::formatXmlErrors($errors));
+
+ self::assertStringEqualsFile(self::TEST_FEED_XML_PATH_3, $feed->saveXML());
+ }
+
+ /**
+ * @group buildXML
+ *
+ * @codeCoverageIgnore
+ */
+ public function testFeedCreationException1(): void
+ {
+ $entry = new Entry();
+ $this->expectException(InvalidArgumentException::class);
+ $entry->setContent(null, 'text');
+ }
+
+ /**
+ * @group buildXML
+ *
+ * @codeCoverageIgnore
+ */
+ public function testFeedCreationException2(): void
+ {
+ $entry = new Entry();
+ $this->expectException(InvalidArgumentException::class);
+ $entry->setContent(null, 'xhtml', 'xxx');
+ }
+
+ /**
+ * @group buildXML
+ *
+ * @codeCoverageIgnore
+ */
+ public function testFeedCreationException3(): void
+ {
+ $entry = new Entry();
+ $this->expectException(InvalidArgumentException::class);
+ $entry->setId('xxx');
+ }
+
+ /**
+ * @param null|libXMLError[] $errors
+ *
+ * @return string
+ *
+ * @codeCoverageIgnore
+ */
+ protected static function formatXmlErrors(?array $errors): string
+ {
+ $messages = [];
+ foreach ($errors as $error) {
+ $messages[] = trim($error->message);
+ }
+
+ return implode(PHP_EOL, $messages);
+ }
+}
diff --git a/tests/feed_1.xml b/tests/feed_1.xml
new file mode 100644
index 0000000..5af8772
--- /dev/null
+++ b/tests/feed_1.xml
@@ -0,0 +1,50 @@
+
+
+ tag:test
+ title
+ 2019-05-04T20:00:40+00:00
+ ©2019
+
+
+
+ author
+ author@test.com
+ http://test.com/author
+
+
+ author
+ author@test.com
+ http://test.com/author
+
+
+ contributor
+ contributor@test.com
+ http://test.com/contributor
+
+ subtitle
+ http://test.com/logo
+ http://test.com/icon
+ generator
+ hourly
+ 10
+
+ tag:entry-test
+ entry title
+ 2019-05-04T21:00:40+00:00
+ ©2019
+
+
+
+ author
+ test@test.com
+ http://test.com/author
+
+
+ contributor
+ contributor@test.com
+ http://test.com/contributor
+
+ entry summary
+ Entry content & ...]]>
+
+
diff --git a/tests/feed_2.xml b/tests/feed_2.xml
new file mode 100644
index 0000000..993192f
--- /dev/null
+++ b/tests/feed_2.xml
@@ -0,0 +1,2 @@
+
+tag:testtitle2019-05-04T20:00:40+00:00tag:entry-test2019-05-04T21:00:40+00:00
diff --git a/tests/feed_3.xml b/tests/feed_3.xml
new file mode 100644
index 0000000..40a2650
--- /dev/null
+++ b/tests/feed_3.xml
@@ -0,0 +1,11 @@
+
+
+ tag:test
+ title
+ 2019-05-04T20:00:40+00:00
+
+ tag:entry-test
+
+ 2019-05-04T21:00:40+00:00
+
+