diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..5e1346c
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,12 @@
+/vendor/
+/composer.phar
+
+.DS_Store
+*.swp
+*.swo
+.local.vimrc
+.vimrc.local
+*~
+/.idea/
+/nbproject/
+/local/
diff --git a/.travis.yml b/.travis.yml
new file mode 100644
index 0000000..f7a2680
--- /dev/null
+++ b/.travis.yml
@@ -0,0 +1,20 @@
+language: php
+
+cache:
+ directories:
+ $HOME/.composer/cache/files
+
+php:
+ - 7.0
+
+install:
+ - php -n ~/.phpenv/versions/$(phpenv version-name)/bin/composer self-update
+ - php -n ~/.phpenv/versions/$(phpenv version-name)/bin/composer require satooshi/php-coveralls
+ - php -n ~/.phpenv/versions/$(phpenv version-name)/bin/composer update
+
+script:
+ - php -n ~/.phpenv/versions/$(phpenv version-name)/bin/composer lint
+ - phpunit --coverage-clover build/logs/clover.xml
+
+after_success:
+ - travis_retry php -n vendor/bin/coveralls
diff --git a/LICENSE b/LICENSE
new file mode 100644
index 0000000..ac6df0e
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,21 @@
+The MIT License (MIT)
+
+Copyright (c) 2016 Vanio Solutions
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..1209dbc
--- /dev/null
+++ b/README.md
@@ -0,0 +1,107 @@
+# Doctrine Domain Events
+
+[![Build Status](https://travis-ci.org/vaniocz/doctrine-domain-events.svg?branch=master)](https://travis-ci.org/vaniocz/doctrine-domain-events)
+[![Coverage Status](https://coveralls.io/repos/github/vaniocz/doctrine-domain-events/badge.svg?branch=master)](https://coveralls.io/github/vaniocz/doctrine-domain-events?branch=master)
+![PHP7](https://img.shields.io/badge/php-7-6B7EB9.svg)
+[![License](https://poser.pugx.org/vanio/doctrine-domain-events/license)](https://github.com/vaniocz/doctrine-domain-events/blob/master/LICENSE)
+
+Very lightweight extension for Doctrine2 ORM allowing usage of domain events together with an ability to call flush
+inside it's listeners. This library is inspired in Beberlei's
+[Doctrine and Domain Events article](http://www.whitewashing.de/2013/07/24/doctrine_and_domainevents.html).
+
+# Installation
+Installation can be done as usually using composer.
+`composer require vanio/doctrine-domain-events`
+
+You also need to register an instance of `Vanio\DoctrineDomainEvents\DoctrineDomainEventDispatcher` inside Doctrine's
+event manager.
+
+```php
+use Vanio\DoctrineDomainEvents\DoctrineDomainEventDispatcher;
+
+$eventManager->addSubscriber(new DoctrineDomainEventDispatcher);
+```
+
+# Usage
+
+## Setting up your entity
+First make sure your entity implements `Vanio\DoctrineDomainEvent` interface and uses the
+`Vanio\DoctrineDomainEvent\EventProviderTrait`.
+```php
+use Vanio\DoctrineDomainEvent\EventProvider;
+use Vanio\DoctrineDomainEvent\EventProviderTrait;
+
+class MyEntity implements EventProvider
+{
+ use EventProviderTrait;
+}
+```
+
+## Raising domain events
+To raise a domain event from your entity use the `raise` method. This method expects either an instance of
+`Vanio\DoctrineDomainEvent\DomainEvent` or just a string representing the domain event name (and optional array of
+properties). In case of passing a string it will be turned into an instance of the `DomainEvent` class. If you prefer to
+create your own event classes you can do so by extending the `DomainEvent` class, just don't forget to extend the `name`
+method. The event is dispatched at the end of transaction once your entity has been flushed and all the changes are
+projected into database so it is possible to both perform database queries over the changes as well as cancel the
+transaction. Event names will be used as method names of corresponding listeners because this implementation uses the
+built-in Doctrine event manager to keep it simple thus you need to make sure all your **event names are globally
+unique**.
+
+```php
+use Vanio\DoctrineDomainEvent\EventProvider;
+use Vanio\DoctrineDomainEvent\EventProviderTrait;
+
+class Article implements EventProvider
+{
+ use EventProviderTrait;
+
+ const EVENT_ARTICLE_PUBLISHED = 'onArticlePublish';
+
+ // ...
+
+ public function publish()
+ {
+ $this->raise(self::EVENT_ARTICLE_PUBLISHED, ['property' => 'value']);
+ }
+}
+```
+
+## Listening to domain events
+Listening to domain events is done the same way as listening to standard Doctrine events because it uses the same event
+manager. You need to either prepare a listener and register it to appropriate domain event yourself or you can use a
+subscriber that know which events it listens to. More information about the event system can be found inside
+[Doctrine documentation](http://docs.doctrine-project.org/projects/doctrine-orm/en/latest/reference/events.html).
+
+### Listening to domain events using a listener
+```php
+class Listener
+{
+ public function onArticlePublish(DomainEvent $event)
+ {
+ // ...
+ }
+}
+
+$eventManager->addListener(Article::EVENT_ARTICLE_PUBLISHED, new Listener);
+```
+
+### Listening to domain events using a subscriber
+```php
+use Doctrine\Common\EventSubscriber;
+
+class Subscriber implements EventSubscriber
+{
+ public function onArticlePublish(DomainEvent $event)
+ {
+ // ...
+ }
+
+ public function getSubscribedEvents(): array
+ {
+ return [Article::EVENT_ARTICLE_PUBLISHED];
+ }
+}
+
+$eventManager->addSubscriber(new Subscriber);
+```
diff --git a/composer.json b/composer.json
new file mode 100644
index 0000000..5558e4e
--- /dev/null
+++ b/composer.json
@@ -0,0 +1,41 @@
+{
+ "name": "vanio/doctrine-domain-events",
+ "description": "An extension for Doctrine2 ORM allowing usage of domain events and an ability to call flush inside events triggered by flush.",
+ "keywords": ["doctrine", "doctrine2", "domain events"],
+ "homepage": "https://github.com/vaniocz/doctrine-domain-events",
+ "license": "MIT",
+ "authors": [
+ {"name": "Marek Štípek", "email": "marek.stipek@vanio.cz"}
+ ],
+ "require": {
+ "php": "7.0.*",
+ "doctrine/orm": "^2.5",
+ "vanio/stdlib": "^0.1@dev",
+ "vanio/type-parser": "^0.1@dev"
+ },
+ "require-dev": {
+ "doctrine/orm": "dev-master#9da83cf",
+ "phpunit/phpunit": "^5.5",
+ "vanio/coding-standards": "^0.1@dev"
+ },
+ "autoload": {
+ "psr-4": {
+ "Vanio\\DoctrineDomainEvents\\": "src/"
+ },
+ "exclude-from-classmap": ["/tests/"]
+ },
+ "autoload-dev": {
+ "psr-0": {"Doctrine\\Tests\\": "vendor/doctrine/orm/tests/"},
+ "psr-4": {"Vanio\\DoctrineDomainEvents\\Tests\\": "tests/"}
+ },
+ "scripts": {
+ "test": "\"vendor/bin/phpunit\"",
+ "lint": "\"vendor/bin/phpcs\" --standard=ruleset.xml --extensions=php --encoding=utf-8 --ignore=vendor .",
+ "fix": "\"vendor/bin/phpcbf\" --standard=ruleset.xml --extensions=php --encoding=utf-8 --no-patch --ignore=vendor ."
+ },
+ "extra": {
+ "branch-alias": {
+ "dev-master": "0.1.x-dev"
+ }
+ }
+}
diff --git a/composer.lock b/composer.lock
new file mode 100644
index 0000000..9867f6d
--- /dev/null
+++ b/composer.lock
@@ -0,0 +1,2489 @@
+{
+ "_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#composer-lock-the-lock-file",
+ "This file is @generated automatically"
+ ],
+ "hash": "434d7ecbea9599700d512fd125ba5ac1",
+ "content-hash": "c15a57147474da8043fba8779795bac9",
+ "packages": [
+ {
+ "name": "doctrine/annotations",
+ "version": "v1.2.7",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/doctrine/annotations.git",
+ "reference": "f25c8aab83e0c3e976fd7d19875f198ccf2f7535"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/doctrine/annotations/zipball/f25c8aab83e0c3e976fd7d19875f198ccf2f7535",
+ "reference": "f25c8aab83e0c3e976fd7d19875f198ccf2f7535",
+ "shasum": ""
+ },
+ "require": {
+ "doctrine/lexer": "1.*",
+ "php": ">=5.3.2"
+ },
+ "require-dev": {
+ "doctrine/cache": "1.*",
+ "phpunit/phpunit": "4.*"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "1.3.x-dev"
+ }
+ },
+ "autoload": {
+ "psr-0": {
+ "Doctrine\\Common\\Annotations\\": "lib/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Roman Borschel",
+ "email": "roman@code-factory.org"
+ },
+ {
+ "name": "Benjamin Eberlei",
+ "email": "kontakt@beberlei.de"
+ },
+ {
+ "name": "Guilherme Blanco",
+ "email": "guilhermeblanco@gmail.com"
+ },
+ {
+ "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": "2015-08-31 12:32:49"
+ },
+ {
+ "name": "doctrine/cache",
+ "version": "v1.6.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/doctrine/cache.git",
+ "reference": "f8af318d14bdb0eff0336795b428b547bd39ccb6"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/doctrine/cache/zipball/f8af318d14bdb0eff0336795b428b547bd39ccb6",
+ "reference": "f8af318d14bdb0eff0336795b428b547bd39ccb6",
+ "shasum": ""
+ },
+ "require": {
+ "php": "~5.5|~7.0"
+ },
+ "conflict": {
+ "doctrine/common": ">2.2,<2.4"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "~4.8|~5.0",
+ "predis/predis": "~1.0",
+ "satooshi/php-coveralls": "~0.6"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "1.6.x-dev"
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "Doctrine\\Common\\Cache\\": "lib/Doctrine/Common/Cache"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Roman Borschel",
+ "email": "roman@code-factory.org"
+ },
+ {
+ "name": "Benjamin Eberlei",
+ "email": "kontakt@beberlei.de"
+ },
+ {
+ "name": "Guilherme Blanco",
+ "email": "guilhermeblanco@gmail.com"
+ },
+ {
+ "name": "Jonathan Wage",
+ "email": "jonwage@gmail.com"
+ },
+ {
+ "name": "Johannes Schmitt",
+ "email": "schmittjoh@gmail.com"
+ }
+ ],
+ "description": "Caching library offering an object-oriented API for many cache backends",
+ "homepage": "http://www.doctrine-project.org",
+ "keywords": [
+ "cache",
+ "caching"
+ ],
+ "time": "2015-12-31 16:37:02"
+ },
+ {
+ "name": "doctrine/collections",
+ "version": "v1.3.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/doctrine/collections.git",
+ "reference": "6c1e4eef75f310ea1b3e30945e9f06e652128b8a"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/doctrine/collections/zipball/6c1e4eef75f310ea1b3e30945e9f06e652128b8a",
+ "reference": "6c1e4eef75f310ea1b3e30945e9f06e652128b8a",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=5.3.2"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "~4.0"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "1.2.x-dev"
+ }
+ },
+ "autoload": {
+ "psr-0": {
+ "Doctrine\\Common\\Collections\\": "lib/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Roman Borschel",
+ "email": "roman@code-factory.org"
+ },
+ {
+ "name": "Benjamin Eberlei",
+ "email": "kontakt@beberlei.de"
+ },
+ {
+ "name": "Guilherme Blanco",
+ "email": "guilhermeblanco@gmail.com"
+ },
+ {
+ "name": "Jonathan Wage",
+ "email": "jonwage@gmail.com"
+ },
+ {
+ "name": "Johannes Schmitt",
+ "email": "schmittjoh@gmail.com"
+ }
+ ],
+ "description": "Collections Abstraction library",
+ "homepage": "http://www.doctrine-project.org",
+ "keywords": [
+ "array",
+ "collections",
+ "iterator"
+ ],
+ "time": "2015-04-14 22:21:58"
+ },
+ {
+ "name": "doctrine/common",
+ "version": "v2.6.1",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/doctrine/common.git",
+ "reference": "a579557bc689580c19fee4e27487a67fe60defc0"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/doctrine/common/zipball/a579557bc689580c19fee4e27487a67fe60defc0",
+ "reference": "a579557bc689580c19fee4e27487a67fe60defc0",
+ "shasum": ""
+ },
+ "require": {
+ "doctrine/annotations": "1.*",
+ "doctrine/cache": "1.*",
+ "doctrine/collections": "1.*",
+ "doctrine/inflector": "1.*",
+ "doctrine/lexer": "1.*",
+ "php": "~5.5|~7.0"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "~4.8|~5.0"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "2.7.x-dev"
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "Doctrine\\Common\\": "lib/Doctrine/Common"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Roman Borschel",
+ "email": "roman@code-factory.org"
+ },
+ {
+ "name": "Benjamin Eberlei",
+ "email": "kontakt@beberlei.de"
+ },
+ {
+ "name": "Guilherme Blanco",
+ "email": "guilhermeblanco@gmail.com"
+ },
+ {
+ "name": "Jonathan Wage",
+ "email": "jonwage@gmail.com"
+ },
+ {
+ "name": "Johannes Schmitt",
+ "email": "schmittjoh@gmail.com"
+ }
+ ],
+ "description": "Common Library for Doctrine projects",
+ "homepage": "http://www.doctrine-project.org",
+ "keywords": [
+ "annotations",
+ "collections",
+ "eventmanager",
+ "persistence",
+ "spl"
+ ],
+ "time": "2015-12-25 13:18:31"
+ },
+ {
+ "name": "doctrine/dbal",
+ "version": "v2.5.5",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/doctrine/dbal.git",
+ "reference": "9f8c05cd5225a320d56d4bfdb4772f10d045a0c9"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/doctrine/dbal/zipball/9f8c05cd5225a320d56d4bfdb4772f10d045a0c9",
+ "reference": "9f8c05cd5225a320d56d4bfdb4772f10d045a0c9",
+ "shasum": ""
+ },
+ "require": {
+ "doctrine/common": ">=2.4,<2.7-dev",
+ "php": ">=5.3.2"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "4.*",
+ "symfony/console": "2.*||^3.0"
+ },
+ "suggest": {
+ "symfony/console": "For helpful console commands such as SQL execution and import of files."
+ },
+ "bin": [
+ "bin/doctrine-dbal"
+ ],
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "2.5.x-dev"
+ }
+ },
+ "autoload": {
+ "psr-0": {
+ "Doctrine\\DBAL\\": "lib/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Roman Borschel",
+ "email": "roman@code-factory.org"
+ },
+ {
+ "name": "Benjamin Eberlei",
+ "email": "kontakt@beberlei.de"
+ },
+ {
+ "name": "Guilherme Blanco",
+ "email": "guilhermeblanco@gmail.com"
+ },
+ {
+ "name": "Jonathan Wage",
+ "email": "jonwage@gmail.com"
+ }
+ ],
+ "description": "Database Abstraction Layer",
+ "homepage": "http://www.doctrine-project.org",
+ "keywords": [
+ "database",
+ "dbal",
+ "persistence",
+ "queryobject"
+ ],
+ "time": "2016-09-09 19:13:33"
+ },
+ {
+ "name": "doctrine/inflector",
+ "version": "v1.1.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/doctrine/inflector.git",
+ "reference": "90b2128806bfde671b6952ab8bea493942c1fdae"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/doctrine/inflector/zipball/90b2128806bfde671b6952ab8bea493942c1fdae",
+ "reference": "90b2128806bfde671b6952ab8bea493942c1fdae",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=5.3.2"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "4.*"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "1.1.x-dev"
+ }
+ },
+ "autoload": {
+ "psr-0": {
+ "Doctrine\\Common\\Inflector\\": "lib/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Roman Borschel",
+ "email": "roman@code-factory.org"
+ },
+ {
+ "name": "Benjamin Eberlei",
+ "email": "kontakt@beberlei.de"
+ },
+ {
+ "name": "Guilherme Blanco",
+ "email": "guilhermeblanco@gmail.com"
+ },
+ {
+ "name": "Jonathan Wage",
+ "email": "jonwage@gmail.com"
+ },
+ {
+ "name": "Johannes Schmitt",
+ "email": "schmittjoh@gmail.com"
+ }
+ ],
+ "description": "Common String Manipulations with regard to casing and singular/plural rules.",
+ "homepage": "http://www.doctrine-project.org",
+ "keywords": [
+ "inflection",
+ "pluralize",
+ "singularize",
+ "string"
+ ],
+ "time": "2015-11-06 14:35:42"
+ },
+ {
+ "name": "doctrine/instantiator",
+ "version": "1.0.5",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/doctrine/instantiator.git",
+ "reference": "8e884e78f9f0eb1329e445619e04456e64d8051d"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/doctrine/instantiator/zipball/8e884e78f9f0eb1329e445619e04456e64d8051d",
+ "reference": "8e884e78f9f0eb1329e445619e04456e64d8051d",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=5.3,<8.0-DEV"
+ },
+ "require-dev": {
+ "athletic/athletic": "~0.1.8",
+ "ext-pdo": "*",
+ "ext-phar": "*",
+ "phpunit/phpunit": "~4.0",
+ "squizlabs/php_codesniffer": "~2.0"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "1.0.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://github.com/doctrine/instantiator",
+ "keywords": [
+ "constructor",
+ "instantiate"
+ ],
+ "time": "2015-06-14 21:17:01"
+ },
+ {
+ "name": "doctrine/lexer",
+ "version": "v1.0.1",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/doctrine/lexer.git",
+ "reference": "83893c552fd2045dd78aef794c31e694c37c0b8c"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/doctrine/lexer/zipball/83893c552fd2045dd78aef794c31e694c37c0b8c",
+ "reference": "83893c552fd2045dd78aef794c31e694c37c0b8c",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=5.3.2"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "1.0.x-dev"
+ }
+ },
+ "autoload": {
+ "psr-0": {
+ "Doctrine\\Common\\Lexer\\": "lib/"
+ }
+ },
+ "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": "Base library for a lexer that can be used in Top-Down, Recursive Descent Parsers.",
+ "homepage": "http://www.doctrine-project.org",
+ "keywords": [
+ "lexer",
+ "parser"
+ ],
+ "time": "2014-09-09 13:34:57"
+ },
+ {
+ "name": "doctrine/orm",
+ "version": "dev-master",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/doctrine/doctrine2.git",
+ "reference": "9da83cf"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/doctrine/doctrine2/zipball/9da83cf",
+ "reference": "9da83cf",
+ "shasum": ""
+ },
+ "require": {
+ "doctrine/cache": "~1.4",
+ "doctrine/collections": "~1.2",
+ "doctrine/common": ">=2.5-dev,<2.7-dev",
+ "doctrine/dbal": ">=2.5-dev,<2.7-dev",
+ "doctrine/instantiator": "~1.0.1",
+ "ext-pdo": "*",
+ "php": "^5.6 || ^7.0",
+ "symfony/console": "~2.5|~3.0"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "^5.4",
+ "symfony/yaml": "~2.3|~3.0"
+ },
+ "suggest": {
+ "symfony/yaml": "If you want to use YAML Metadata Mapping Driver"
+ },
+ "bin": [
+ "bin/doctrine"
+ ],
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "2.6.x-dev"
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "Doctrine\\ORM\\": "lib/Doctrine/ORM"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Roman Borschel",
+ "email": "roman@code-factory.org"
+ },
+ {
+ "name": "Benjamin Eberlei",
+ "email": "kontakt@beberlei.de"
+ },
+ {
+ "name": "Guilherme Blanco",
+ "email": "guilhermeblanco@gmail.com"
+ },
+ {
+ "name": "Jonathan Wage",
+ "email": "jonwage@gmail.com"
+ },
+ {
+ "name": "Marco Pivetta",
+ "email": "ocramius@gmail.com"
+ }
+ ],
+ "description": "Object-Relational-Mapper for PHP",
+ "homepage": "http://www.doctrine-project.org",
+ "keywords": [
+ "database",
+ "orm"
+ ],
+ "time": "2016-06-18 11:01:59"
+ },
+ {
+ "name": "psr/log",
+ "version": "1.0.2",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/php-fig/log.git",
+ "reference": "4ebe3a8bf773a19edfe0a84b6585ba3d401b724d"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/php-fig/log/zipball/4ebe3a8bf773a19edfe0a84b6585ba3d401b724d",
+ "reference": "4ebe3a8bf773a19edfe0a84b6585ba3d401b724d",
+ "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": "2016-10-10 12:19:37"
+ },
+ {
+ "name": "symfony/console",
+ "version": "v3.1.5",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/symfony/console.git",
+ "reference": "6cb0872fb57b38b3b09ff213c21ed693956b9eb0"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/symfony/console/zipball/6cb0872fb57b38b3b09ff213c21ed693956b9eb0",
+ "reference": "6cb0872fb57b38b3b09ff213c21ed693956b9eb0",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=5.5.9",
+ "symfony/debug": "~2.8|~3.0",
+ "symfony/polyfill-mbstring": "~1.0"
+ },
+ "require-dev": {
+ "psr/log": "~1.0",
+ "symfony/event-dispatcher": "~2.8|~3.0",
+ "symfony/process": "~2.8|~3.0"
+ },
+ "suggest": {
+ "psr/log": "For using the console logger",
+ "symfony/event-dispatcher": "",
+ "symfony/process": ""
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "3.1-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": "2016-09-28 00:11:12"
+ },
+ {
+ "name": "symfony/debug",
+ "version": "v3.1.5",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/symfony/debug.git",
+ "reference": "e2b3f74a67fc928adc3c1b9027f73e1bc01190a8"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/symfony/debug/zipball/e2b3f74a67fc928adc3c1b9027f73e1bc01190a8",
+ "reference": "e2b3f74a67fc928adc3c1b9027f73e1bc01190a8",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=5.5.9",
+ "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/class-loader": "~2.8|~3.0",
+ "symfony/http-kernel": "~2.8|~3.0"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "3.1-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": "2016-09-06 11:02:40"
+ },
+ {
+ "name": "symfony/polyfill-mbstring",
+ "version": "v1.2.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/symfony/polyfill-mbstring.git",
+ "reference": "dff51f72b0706335131b00a7f49606168c582594"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/dff51f72b0706335131b00a7f49606168c582594",
+ "reference": "dff51f72b0706335131b00a7f49606168c582594",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=5.3.3"
+ },
+ "suggest": {
+ "ext-mbstring": "For best performance"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "1.2-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": "2016-05-18 14:26:46"
+ },
+ {
+ "name": "vanio/stdlib",
+ "version": "dev-master",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/vaniocz/stdlib.git",
+ "reference": "51cfa081276fcac8d7900830ffb4fa08a1da26e0"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/vaniocz/stdlib/zipball/51cfa081276fcac8d7900830ffb4fa08a1da26e0",
+ "reference": "51cfa081276fcac8d7900830ffb4fa08a1da26e0",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=7.0"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "^5.5",
+ "slevomat/coding-standard": "dev-master as 1.x-dev",
+ "vanio/coding-standards": "^0.1@dev"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "0.1.x-dev"
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "Vanio\\Stdlib\\": "src/"
+ },
+ "exclude-from-classmap": [
+ "/tests/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Marek Štípek",
+ "email": "marek.stipek@vanio.cz"
+ },
+ {
+ "name": "Adam Hojka"
+ }
+ ],
+ "description": "General purpose classes extending the PHP language.",
+ "homepage": "https://github.com/vaniocz/stdlib",
+ "keywords": [
+ "enum",
+ "object utility",
+ "objects",
+ "standard library",
+ "string utility",
+ "strings",
+ "uri value object"
+ ],
+ "time": "2016-09-18 18:00:19"
+ },
+ {
+ "name": "vanio/type-parser",
+ "version": "dev-master",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/vaniocz/type-parser.git",
+ "reference": "0f0d7ddebf053bac0df92f6e28f73224fd5f0544"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/vaniocz/type-parser/zipball/0f0d7ddebf053bac0df92f6e28f73224fd5f0544",
+ "reference": "0f0d7ddebf053bac0df92f6e28f73224fd5f0544",
+ "shasum": ""
+ },
+ "require": {
+ "doctrine/annotations": "^1.2",
+ "doctrine/cache": "^1.6",
+ "php": ">=7.0"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "^5.5",
+ "vanio/coding-standards": "^0.1@dev"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "0.1.x-dev"
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "Vanio\\TypeParser\\": "src/"
+ },
+ "exclude-from-classmap": [
+ "/tests/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Marek Štípek",
+ "email": "marek.stipek@vanio.cz"
+ }
+ ],
+ "description": "Library for parsing property types defined using @var PHPDoc annotation",
+ "homepage": "https://github.com/vaniocz/type-parser",
+ "keywords": [
+ "annotation",
+ "docblock",
+ "parser",
+ "type",
+ "type resolver",
+ "var"
+ ],
+ "time": "2016-09-17 00:49:00"
+ }
+ ],
+ "packages-dev": [
+ {
+ "name": "consistence/coding-standard",
+ "version": "0.11.1",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/consistence/coding-standard.git",
+ "reference": "657dba30487a43b3030ad77fd09bc99d909ef380"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/consistence/coding-standard/zipball/657dba30487a43b3030ad77fd09bc99d909ef380",
+ "reference": "657dba30487a43b3030ad77fd09bc99d909ef380",
+ "shasum": ""
+ },
+ "require": {
+ "php": "~5.6|~7.0",
+ "squizlabs/php_codesniffer": "~2.6.2"
+ },
+ "require-dev": {
+ "jakub-onderka/php-console-highlighter": "0.3.2",
+ "jakub-onderka/php-parallel-lint": "0.9.2",
+ "phing/phing": "2.14",
+ "phpunit/phpunit": "5.4.6"
+ },
+ "type": "library",
+ "autoload": {
+ "psr-4": {
+ "Consistence\\": [
+ "Consistence"
+ ]
+ },
+ "classmap": [
+ "Consistence"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Vašek Purchart",
+ "email": "me@vasekpurchart.cz",
+ "homepage": "http://vasekpurchart.cz"
+ }
+ ],
+ "description": "Consistence - Coding Standard - PHP Code Sniffer rules",
+ "keywords": [
+ "Coding Standard",
+ "PHPCodeSniffer",
+ "codesniffer",
+ "coding",
+ "cs",
+ "phpcs",
+ "ruleset",
+ "sniffer",
+ "standard"
+ ],
+ "time": "2016-07-26 18:03:40"
+ },
+ {
+ "name": "jakub-onderka/php-parallel-lint",
+ "version": "v0.9.2",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/JakubOnderka/PHP-Parallel-Lint.git",
+ "reference": "2ead2e4043ab125bee9554f356e0a86742c2d4fa"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/JakubOnderka/PHP-Parallel-Lint/zipball/2ead2e4043ab125bee9554f356e0a86742c2d4fa",
+ "reference": "2ead2e4043ab125bee9554f356e0a86742c2d4fa",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=5.3.3"
+ },
+ "require-dev": {
+ "jakub-onderka/php-console-highlighter": "~0.3",
+ "nette/tester": "~1.3"
+ },
+ "suggest": {
+ "jakub-onderka/php-console-highlighter": "Highlight syntax in code snippet"
+ },
+ "bin": [
+ "parallel-lint"
+ ],
+ "type": "library",
+ "autoload": {
+ "classmap": [
+ "./"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "BSD-2-Clause"
+ ],
+ "authors": [
+ {
+ "name": "Jakub Onderka",
+ "email": "jakub.onderka@gmail.com"
+ }
+ ],
+ "description": "This tool check syntax of PHP files about 20x faster than serial check.",
+ "homepage": "https://github.com/JakubOnderka/PHP-Parallel-Lint",
+ "time": "2015-12-15 10:42:16"
+ },
+ {
+ "name": "myclabs/deep-copy",
+ "version": "1.5.4",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/myclabs/DeepCopy.git",
+ "reference": "ea74994a3dc7f8d2f65a06009348f2d63c81e61f"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/ea74994a3dc7f8d2f65a06009348f2d63c81e61f",
+ "reference": "ea74994a3dc7f8d2f65a06009348f2d63c81e61f",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=5.4.0"
+ },
+ "require-dev": {
+ "doctrine/collections": "1.*",
+ "phpunit/phpunit": "~4.1"
+ },
+ "type": "library",
+ "autoload": {
+ "psr-4": {
+ "DeepCopy\\": "src/DeepCopy/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "description": "Create deep copies (clones) of your objects",
+ "homepage": "https://github.com/myclabs/DeepCopy",
+ "keywords": [
+ "clone",
+ "copy",
+ "duplicate",
+ "object",
+ "object graph"
+ ],
+ "time": "2016-09-16 13:37:59"
+ },
+ {
+ "name": "phpdocumentor/reflection-common",
+ "version": "1.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/phpDocumentor/ReflectionCommon.git",
+ "reference": "144c307535e82c8fdcaacbcfc1d6d8eeb896687c"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/phpDocumentor/ReflectionCommon/zipball/144c307535e82c8fdcaacbcfc1d6d8eeb896687c",
+ "reference": "144c307535e82c8fdcaacbcfc1d6d8eeb896687c",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=5.5"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "^4.6"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "1.0.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": "2015-12-27 11:43:31"
+ },
+ {
+ "name": "phpdocumentor/reflection-docblock",
+ "version": "3.1.1",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/phpDocumentor/ReflectionDocBlock.git",
+ "reference": "8331b5efe816ae05461b7ca1e721c01b46bafb3e"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/8331b5efe816ae05461b7ca1e721c01b46bafb3e",
+ "reference": "8331b5efe816ae05461b7ca1e721c01b46bafb3e",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=5.5",
+ "phpdocumentor/reflection-common": "^1.0@dev",
+ "phpdocumentor/type-resolver": "^0.2.0",
+ "webmozart/assert": "^1.0"
+ },
+ "require-dev": {
+ "mockery/mockery": "^0.9.4",
+ "phpunit/phpunit": "^4.4"
+ },
+ "type": "library",
+ "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": "2016-09-30 07:12:33"
+ },
+ {
+ "name": "phpdocumentor/type-resolver",
+ "version": "0.2",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/phpDocumentor/TypeResolver.git",
+ "reference": "b39c7a5b194f9ed7bd0dd345c751007a41862443"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/phpDocumentor/TypeResolver/zipball/b39c7a5b194f9ed7bd0dd345c751007a41862443",
+ "reference": "b39c7a5b194f9ed7bd0dd345c751007a41862443",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=5.5",
+ "phpdocumentor/reflection-common": "^1.0"
+ },
+ "require-dev": {
+ "mockery/mockery": "^0.9.4",
+ "phpunit/phpunit": "^5.2||^4.8.24"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "1.0.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"
+ }
+ ],
+ "time": "2016-06-10 07:14:17"
+ },
+ {
+ "name": "phpspec/prophecy",
+ "version": "v1.6.1",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/phpspec/prophecy.git",
+ "reference": "58a8137754bc24b25740d4281399a4a3596058e0"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/phpspec/prophecy/zipball/58a8137754bc24b25740d4281399a4a3596058e0",
+ "reference": "58a8137754bc24b25740d4281399a4a3596058e0",
+ "shasum": ""
+ },
+ "require": {
+ "doctrine/instantiator": "^1.0.2",
+ "php": "^5.3|^7.0",
+ "phpdocumentor/reflection-docblock": "^2.0|^3.0.2",
+ "sebastian/comparator": "^1.1",
+ "sebastian/recursion-context": "^1.0"
+ },
+ "require-dev": {
+ "phpspec/phpspec": "^2.0"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "1.6.x-dev"
+ }
+ },
+ "autoload": {
+ "psr-0": {
+ "Prophecy\\": "src/"
+ }
+ },
+ "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": "2016-06-07 08:13:47"
+ },
+ {
+ "name": "phpunit/php-code-coverage",
+ "version": "4.0.1",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/sebastianbergmann/php-code-coverage.git",
+ "reference": "5f3f7e736d6319d5f1fc402aff8b026da26709a3"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/5f3f7e736d6319d5f1fc402aff8b026da26709a3",
+ "reference": "5f3f7e736d6319d5f1fc402aff8b026da26709a3",
+ "shasum": ""
+ },
+ "require": {
+ "php": "^5.6 || ^7.0",
+ "phpunit/php-file-iterator": "~1.3",
+ "phpunit/php-text-template": "~1.2",
+ "phpunit/php-token-stream": "^1.4.2",
+ "sebastian/code-unit-reverse-lookup": "~1.0",
+ "sebastian/environment": "^1.3.2 || ^2.0",
+ "sebastian/version": "~1.0|~2.0"
+ },
+ "require-dev": {
+ "ext-xdebug": ">=2.1.4",
+ "phpunit/phpunit": "^5.4"
+ },
+ "suggest": {
+ "ext-dom": "*",
+ "ext-xdebug": ">=2.4.0",
+ "ext-xmlwriter": "*"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "4.0.x-dev"
+ }
+ },
+ "autoload": {
+ "classmap": [
+ "src/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "BSD-3-Clause"
+ ],
+ "authors": [
+ {
+ "name": "Sebastian Bergmann",
+ "email": "sb@sebastian-bergmann.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": "2016-07-26 14:39:29"
+ },
+ {
+ "name": "phpunit/php-file-iterator",
+ "version": "1.4.1",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/sebastianbergmann/php-file-iterator.git",
+ "reference": "6150bf2c35d3fc379e50c7602b75caceaa39dbf0"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/6150bf2c35d3fc379e50c7602b75caceaa39dbf0",
+ "reference": "6150bf2c35d3fc379e50c7602b75caceaa39dbf0",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=5.3.3"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "1.4.x-dev"
+ }
+ },
+ "autoload": {
+ "classmap": [
+ "src/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "BSD-3-Clause"
+ ],
+ "authors": [
+ {
+ "name": "Sebastian Bergmann",
+ "email": "sb@sebastian-bergmann.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": "2015-06-21 13:08:43"
+ },
+ {
+ "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-21 13:50:34"
+ },
+ {
+ "name": "phpunit/php-timer",
+ "version": "1.0.8",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/sebastianbergmann/php-timer.git",
+ "reference": "38e9124049cf1a164f1e4537caf19c99bf1eb260"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/38e9124049cf1a164f1e4537caf19c99bf1eb260",
+ "reference": "38e9124049cf1a164f1e4537caf19c99bf1eb260",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=5.3.3"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "~4|~5"
+ },
+ "type": "library",
+ "autoload": {
+ "classmap": [
+ "src/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "BSD-3-Clause"
+ ],
+ "authors": [
+ {
+ "name": "Sebastian Bergmann",
+ "email": "sb@sebastian-bergmann.de",
+ "role": "lead"
+ }
+ ],
+ "description": "Utility class for timing",
+ "homepage": "https://github.com/sebastianbergmann/php-timer/",
+ "keywords": [
+ "timer"
+ ],
+ "time": "2016-05-12 18:03:57"
+ },
+ {
+ "name": "phpunit/php-token-stream",
+ "version": "1.4.8",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/sebastianbergmann/php-token-stream.git",
+ "reference": "3144ae21711fb6cac0b1ab4cbe63b75ce3d4e8da"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/sebastianbergmann/php-token-stream/zipball/3144ae21711fb6cac0b1ab4cbe63b75ce3d4e8da",
+ "reference": "3144ae21711fb6cac0b1ab4cbe63b75ce3d4e8da",
+ "shasum": ""
+ },
+ "require": {
+ "ext-tokenizer": "*",
+ "php": ">=5.3.3"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "~4.2"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "1.4-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": "2015-09-15 10:49:45"
+ },
+ {
+ "name": "phpunit/phpunit",
+ "version": "5.6.1",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/sebastianbergmann/phpunit.git",
+ "reference": "60c32c5b5e79c2248001efa2560f831da11cc2d7"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/60c32c5b5e79c2248001efa2560f831da11cc2d7",
+ "reference": "60c32c5b5e79c2248001efa2560f831da11cc2d7",
+ "shasum": ""
+ },
+ "require": {
+ "ext-dom": "*",
+ "ext-json": "*",
+ "ext-libxml": "*",
+ "ext-mbstring": "*",
+ "ext-xml": "*",
+ "myclabs/deep-copy": "~1.3",
+ "php": "^5.6 || ^7.0",
+ "phpspec/prophecy": "^1.3.1",
+ "phpunit/php-code-coverage": "^4.0.1",
+ "phpunit/php-file-iterator": "~1.4",
+ "phpunit/php-text-template": "~1.2",
+ "phpunit/php-timer": "^1.0.6",
+ "phpunit/phpunit-mock-objects": "^3.2",
+ "sebastian/comparator": "~1.1",
+ "sebastian/diff": "~1.2",
+ "sebastian/environment": "^1.3 || ^2.0",
+ "sebastian/exporter": "~1.2",
+ "sebastian/global-state": "~1.0",
+ "sebastian/object-enumerator": "~1.0",
+ "sebastian/resource-operations": "~1.0",
+ "sebastian/version": "~1.0|~2.0",
+ "symfony/yaml": "~2.1|~3.0"
+ },
+ "conflict": {
+ "phpdocumentor/reflection-docblock": "3.0.2"
+ },
+ "require-dev": {
+ "ext-pdo": "*"
+ },
+ "suggest": {
+ "ext-xdebug": "*",
+ "phpunit/php-invoker": "~1.1"
+ },
+ "bin": [
+ "phpunit"
+ ],
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "5.6.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": "The PHP Unit Testing framework.",
+ "homepage": "https://phpunit.de/",
+ "keywords": [
+ "phpunit",
+ "testing",
+ "xunit"
+ ],
+ "time": "2016-10-07 13:03:26"
+ },
+ {
+ "name": "phpunit/phpunit-mock-objects",
+ "version": "3.4.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/sebastianbergmann/phpunit-mock-objects.git",
+ "reference": "238d7a2723bce689c79eeac9c7d5e1d623bb9dc2"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/sebastianbergmann/phpunit-mock-objects/zipball/238d7a2723bce689c79eeac9c7d5e1d623bb9dc2",
+ "reference": "238d7a2723bce689c79eeac9c7d5e1d623bb9dc2",
+ "shasum": ""
+ },
+ "require": {
+ "doctrine/instantiator": "^1.0.2",
+ "php": "^5.6 || ^7.0",
+ "phpunit/php-text-template": "^1.2",
+ "sebastian/exporter": "^1.2"
+ },
+ "conflict": {
+ "phpunit/phpunit": "<5.4.0"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "^5.4"
+ },
+ "suggest": {
+ "ext-soap": "*"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "3.2.x-dev"
+ }
+ },
+ "autoload": {
+ "classmap": [
+ "src/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "BSD-3-Clause"
+ ],
+ "authors": [
+ {
+ "name": "Sebastian Bergmann",
+ "email": "sb@sebastian-bergmann.de",
+ "role": "lead"
+ }
+ ],
+ "description": "Mock Object library for PHPUnit",
+ "homepage": "https://github.com/sebastianbergmann/phpunit-mock-objects/",
+ "keywords": [
+ "mock",
+ "xunit"
+ ],
+ "time": "2016-10-09 07:01:45"
+ },
+ {
+ "name": "sebastian/code-unit-reverse-lookup",
+ "version": "1.0.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/sebastianbergmann/code-unit-reverse-lookup.git",
+ "reference": "c36f5e7cfce482fde5bf8d10d41a53591e0198fe"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/sebastianbergmann/code-unit-reverse-lookup/zipball/c36f5e7cfce482fde5bf8d10d41a53591e0198fe",
+ "reference": "c36f5e7cfce482fde5bf8d10d41a53591e0198fe",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=5.6"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "~5"
+ },
+ "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": "2016-02-13 06:45:14"
+ },
+ {
+ "name": "sebastian/comparator",
+ "version": "1.2.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/sebastianbergmann/comparator.git",
+ "reference": "937efb279bd37a375bcadf584dec0726f84dbf22"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/937efb279bd37a375bcadf584dec0726f84dbf22",
+ "reference": "937efb279bd37a375bcadf584dec0726f84dbf22",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=5.3.3",
+ "sebastian/diff": "~1.2",
+ "sebastian/exporter": "~1.2"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "~4.4"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "1.2.x-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": "http://www.github.com/sebastianbergmann/comparator",
+ "keywords": [
+ "comparator",
+ "compare",
+ "equality"
+ ],
+ "time": "2015-07-26 15:48:44"
+ },
+ {
+ "name": "sebastian/diff",
+ "version": "1.4.1",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/sebastianbergmann/diff.git",
+ "reference": "13edfd8706462032c2f52b4b862974dd46b71c9e"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/13edfd8706462032c2f52b4b862974dd46b71c9e",
+ "reference": "13edfd8706462032c2f52b4b862974dd46b71c9e",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=5.3.3"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "~4.8"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "1.4-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"
+ ],
+ "time": "2015-12-08 07:14:41"
+ },
+ {
+ "name": "sebastian/environment",
+ "version": "1.3.8",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/sebastianbergmann/environment.git",
+ "reference": "be2c607e43ce4c89ecd60e75c6a85c126e754aea"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/be2c607e43ce4c89ecd60e75c6a85c126e754aea",
+ "reference": "be2c607e43ce4c89ecd60e75c6a85c126e754aea",
+ "shasum": ""
+ },
+ "require": {
+ "php": "^5.3.3 || ^7.0"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "^4.8 || ^5.0"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "1.3.x-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": "2016-08-18 05:49:44"
+ },
+ {
+ "name": "sebastian/exporter",
+ "version": "1.2.2",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/sebastianbergmann/exporter.git",
+ "reference": "42c4c2eec485ee3e159ec9884f95b431287edde4"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/42c4c2eec485ee3e159ec9884f95b431287edde4",
+ "reference": "42c4c2eec485ee3e159ec9884f95b431287edde4",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=5.3.3",
+ "sebastian/recursion-context": "~1.0"
+ },
+ "require-dev": {
+ "ext-mbstring": "*",
+ "phpunit/phpunit": "~4.4"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "1.3.x-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"
+ },
+ {
+ "name": "Adam Harvey",
+ "email": "aharvey@php.net"
+ }
+ ],
+ "description": "Provides the functionality to export PHP variables for visualization",
+ "homepage": "http://www.github.com/sebastianbergmann/exporter",
+ "keywords": [
+ "export",
+ "exporter"
+ ],
+ "time": "2016-06-17 09:04:28"
+ },
+ {
+ "name": "sebastian/global-state",
+ "version": "1.1.1",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/sebastianbergmann/global-state.git",
+ "reference": "bc37d50fea7d017d3d340f230811c9f1d7280af4"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/bc37d50fea7d017d3d340f230811c9f1d7280af4",
+ "reference": "bc37d50fea7d017d3d340f230811c9f1d7280af4",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=5.3.3"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "~4.2"
+ },
+ "suggest": {
+ "ext-uopz": "*"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "1.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": "2015-10-12 03:26:01"
+ },
+ {
+ "name": "sebastian/object-enumerator",
+ "version": "1.0.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/sebastianbergmann/object-enumerator.git",
+ "reference": "d4ca2fb70344987502567bc50081c03e6192fb26"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/sebastianbergmann/object-enumerator/zipball/d4ca2fb70344987502567bc50081c03e6192fb26",
+ "reference": "d4ca2fb70344987502567bc50081c03e6192fb26",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=5.6",
+ "sebastian/recursion-context": "~1.0"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "~5"
+ },
+ "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": "Traverses array structures and object graphs to enumerate all referenced objects",
+ "homepage": "https://github.com/sebastianbergmann/object-enumerator/",
+ "time": "2016-01-28 13:25:10"
+ },
+ {
+ "name": "sebastian/recursion-context",
+ "version": "1.0.2",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/sebastianbergmann/recursion-context.git",
+ "reference": "913401df809e99e4f47b27cdd781f4a258d58791"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/913401df809e99e4f47b27cdd781f4a258d58791",
+ "reference": "913401df809e99e4f47b27cdd781f4a258d58791",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=5.3.3"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "~4.4"
+ },
+ "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": "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": "2015-11-11 19:50:13"
+ },
+ {
+ "name": "sebastian/resource-operations",
+ "version": "1.0.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/sebastianbergmann/resource-operations.git",
+ "reference": "ce990bb21759f94aeafd30209e8cfcdfa8bc3f52"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/sebastianbergmann/resource-operations/zipball/ce990bb21759f94aeafd30209e8cfcdfa8bc3f52",
+ "reference": "ce990bb21759f94aeafd30209e8cfcdfa8bc3f52",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=5.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": "Provides a list of PHP built-in functions that operate on resources",
+ "homepage": "https://www.github.com/sebastianbergmann/resource-operations",
+ "time": "2015-07-28 20:34:47"
+ },
+ {
+ "name": "sebastian/version",
+ "version": "2.0.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/sebastianbergmann/version.git",
+ "reference": "c829badbd8fdf16a0bad8aa7fa7971c029f1b9c5"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/sebastianbergmann/version/zipball/c829badbd8fdf16a0bad8aa7fa7971c029f1b9c5",
+ "reference": "c829badbd8fdf16a0bad8aa7fa7971c029f1b9c5",
+ "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-02-04 12:56:52"
+ },
+ {
+ "name": "slevomat/coding-standard",
+ "version": "1.1.1",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/slevomat/coding-standard.git",
+ "reference": "53c24d3fa620dadc832b6d297f11d908835af97f"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/slevomat/coding-standard/zipball/53c24d3fa620dadc832b6d297f11d908835af97f",
+ "reference": "53c24d3fa620dadc832b6d297f11d908835af97f",
+ "shasum": ""
+ },
+ "require": {
+ "jakub-onderka/php-parallel-lint": "^0.9.2",
+ "php": "^5.6|^7.0",
+ "squizlabs/php_codesniffer": "^2.6.0"
+ },
+ "require-dev": {
+ "consistence/coding-standard": "^0.11.0",
+ "phing/phing": "^2.9",
+ "phpstan/phpstan": "0.1",
+ "phpunit/phpunit": "^5.0",
+ "satooshi/php-coveralls": "^1.0"
+ },
+ "type": "library",
+ "autoload": {
+ "psr-4": {
+ "SlevomatCodingStandard\\": "SlevomatCodingStandard"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "description": "Slevomat Coding Standard for PHP_CodeSniffer extends Consistence Coding Standard by providing sniffs with additional checks.",
+ "time": "2016-08-10 15:35:53"
+ },
+ {
+ "name": "squizlabs/php_codesniffer",
+ "version": "2.6.2",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/squizlabs/PHP_CodeSniffer.git",
+ "reference": "4edb770cb853def6e60c93abb088ad5ac2010c83"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/squizlabs/PHP_CodeSniffer/zipball/4edb770cb853def6e60c93abb088ad5ac2010c83",
+ "reference": "4edb770cb853def6e60c93abb088ad5ac2010c83",
+ "shasum": ""
+ },
+ "require": {
+ "ext-simplexml": "*",
+ "ext-tokenizer": "*",
+ "ext-xmlwriter": "*",
+ "php": ">=5.1.2"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "~4.0"
+ },
+ "bin": [
+ "scripts/phpcs",
+ "scripts/phpcbf"
+ ],
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "2.x-dev"
+ }
+ },
+ "autoload": {
+ "classmap": [
+ "CodeSniffer.php",
+ "CodeSniffer/CLI.php",
+ "CodeSniffer/Exception.php",
+ "CodeSniffer/File.php",
+ "CodeSniffer/Fixer.php",
+ "CodeSniffer/Report.php",
+ "CodeSniffer/Reporting.php",
+ "CodeSniffer/Sniff.php",
+ "CodeSniffer/Tokens.php",
+ "CodeSniffer/Reports/",
+ "CodeSniffer/Tokenizers/",
+ "CodeSniffer/DocGenerators/",
+ "CodeSniffer/Standards/AbstractPatternSniff.php",
+ "CodeSniffer/Standards/AbstractScopeSniff.php",
+ "CodeSniffer/Standards/AbstractVariableSniff.php",
+ "CodeSniffer/Standards/IncorrectPatternException.php",
+ "CodeSniffer/Standards/Generic/Sniffs/",
+ "CodeSniffer/Standards/MySource/Sniffs/",
+ "CodeSniffer/Standards/PEAR/Sniffs/",
+ "CodeSniffer/Standards/PSR1/Sniffs/",
+ "CodeSniffer/Standards/PSR2/Sniffs/",
+ "CodeSniffer/Standards/Squiz/Sniffs/",
+ "CodeSniffer/Standards/Zend/Sniffs/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "BSD-3-Clause"
+ ],
+ "authors": [
+ {
+ "name": "Greg Sherwood",
+ "role": "lead"
+ }
+ ],
+ "description": "PHP_CodeSniffer tokenizes PHP, JavaScript and CSS files and detects violations of a defined set of coding standards.",
+ "homepage": "http://www.squizlabs.com/php-codesniffer",
+ "keywords": [
+ "phpcs",
+ "standards"
+ ],
+ "time": "2016-07-13 23:29:13"
+ },
+ {
+ "name": "symfony/yaml",
+ "version": "v3.1.5",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/symfony/yaml.git",
+ "reference": "368b9738d4033c8b93454cb0dbd45d305135a6d3"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/symfony/yaml/zipball/368b9738d4033c8b93454cb0dbd45d305135a6d3",
+ "reference": "368b9738d4033c8b93454cb0dbd45d305135a6d3",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=5.5.9"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "3.1-dev"
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "Symfony\\Component\\Yaml\\": ""
+ },
+ "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 Yaml Component",
+ "homepage": "https://symfony.com",
+ "time": "2016-09-25 08:27:07"
+ },
+ {
+ "name": "vanio/coding-standards",
+ "version": "dev-master",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/vaniocz/coding-standards.git",
+ "reference": "d68861a96391774efa9822e62c43a719ba92c158"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/vaniocz/coding-standards/zipball/d68861a96391774efa9822e62c43a719ba92c158",
+ "reference": "d68861a96391774efa9822e62c43a719ba92c158",
+ "shasum": ""
+ },
+ "require": {
+ "consistence/coding-standard": "^0.11.1",
+ "slevomat/coding-standard": "^1.1.1",
+ "squizlabs/php_codesniffer": "^2.6.2"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "0.1.x-dev"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Marek Štípek",
+ "email": "marek.stipek@vanio.cz"
+ }
+ ],
+ "description": "Vanio Coding Standard Ruleset for PHP_CodeSniffer.",
+ "homepage": "https://github.com/vaniocz/coding-standards",
+ "keywords": [
+ "codesniffer",
+ "coding standards",
+ "conventions"
+ ],
+ "time": "2016-10-20 16:42:51"
+ },
+ {
+ "name": "webmozart/assert",
+ "version": "1.1.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/webmozart/assert.git",
+ "reference": "bb2d123231c095735130cc8f6d31385a44c7b308"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/webmozart/assert/zipball/bb2d123231c095735130cc8f6d31385a44c7b308",
+ "reference": "bb2d123231c095735130cc8f6d31385a44c7b308",
+ "shasum": ""
+ },
+ "require": {
+ "php": "^5.3.3|^7.0"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "^4.6",
+ "sebastian/version": "^1.0.1"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "1.2-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": "2016-08-09 15:02:57"
+ }
+ ],
+ "aliases": [],
+ "minimum-stability": "stable",
+ "stability-flags": {
+ "vanio/stdlib": 20,
+ "vanio/type-parser": 20,
+ "doctrine/orm": 20,
+ "vanio/coding-standards": 20
+ },
+ "prefer-stable": false,
+ "prefer-lowest": false,
+ "platform": {
+ "php": "7.0.*"
+ },
+ "platform-dev": []
+}
diff --git a/phpunit.xml b/phpunit.xml
new file mode 100644
index 0000000..40434b4
--- /dev/null
+++ b/phpunit.xml
@@ -0,0 +1,25 @@
+
+
+
+
+
+ tests
+
+
+
+
+
+ src
+
+
+
diff --git a/ruleset.xml b/ruleset.xml
new file mode 100644
index 0000000..cd6e318
--- /dev/null
+++ b/ruleset.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
diff --git a/src/DoctrineDomainEventDispatcher.php b/src/DoctrineDomainEventDispatcher.php
new file mode 100644
index 0000000..b7cb2e5
--- /dev/null
+++ b/src/DoctrineDomainEventDispatcher.php
@@ -0,0 +1,116 @@
+entityManager = $event->getEntityManager();
+ $this->eventProviders = [];
+ $this->dispatchEventsOnTransactionEnd();
+ }
+
+ public function postRemove(LifecycleEventArgs $event)
+ {
+ $this->entityManager = $event->getEntityManager();
+ $this->keepEventProviders($event->getEntity());
+ $this->dispatchEventsOnTransactionEnd();
+ }
+
+ public function getSubscribedEvents(): array
+ {
+ return [Events::postFlush, Events::postRemove];
+ }
+
+ /**
+ * @param array $a
+ * @param array $b
+ * @return int
+ * @internal
+ */
+ public function compareEventsOrder(array $a, array $b): int
+ {
+ return $a[0] <=> $b[0];
+ }
+
+ /**
+ * @param object $entity
+ */
+ private function keepEventProviders($entity)
+ {
+ if ($entity instanceof EventProvider) {
+ $this->eventProviders[] = $entity;
+ }
+ }
+
+ private function dispatchEventsOnTransactionEnd()
+ {
+ if (!$this->isTransactionEnd()) {
+ return;
+ }
+
+ $events = [];
+
+ foreach ($this->entityManager->getUnitOfWork()->getIdentityMap() as $entities) {
+ foreach ($entities as $entity) {
+ $this->keepEventProviders($entity);
+ }
+ }
+
+ foreach ($this->eventProviders as $eventProvider) {
+ foreach ($eventProvider->popEvents() as $order => $event) {
+ $events[] = [$order, $event];
+ }
+ }
+
+ if (!$events) {
+ return;
+ }
+
+ $this->clearChangeSets();
+ usort($events, [$this, 'compareEventsOrder']);
+
+ foreach ($events as list(, $event)) {
+ $this->entityManager->getEventManager()->dispatchEvent($event->name(), $event);
+ }
+ }
+
+ private function isTransactionEnd(): bool
+ {
+ return !$this->entityManager->getUnitOfWork()->getScheduledEntityDeletions();
+ }
+
+ /**
+ * This dirty hack provides an ability to safely commit the unit of work inside postFlush event.
+ */
+ private function clearChangeSets()
+ {
+ $clearChangeSets = function () {
+ $this->entityInsertions = $this->entityUpdates
+ = $this->entityDeletions
+ = $this->extraUpdates
+ = $this->entityChangeSets
+ = $this->collectionUpdates
+ = $this->collectionDeletions
+ = $this->visitedCollections
+ = $this->scheduledForSynchronization
+ = $this->orphanRemovals
+ = [];
+ };
+ $clearChangeSets = $clearChangeSets->bindTo($this->entityManager->getUnitOfWork(), UnitOfWork::class);
+ $clearChangeSets();
+ }
+}
diff --git a/src/DomainEvent.php b/src/DomainEvent.php
new file mode 100644
index 0000000..61345dc
--- /dev/null
+++ b/src/DomainEvent.php
@@ -0,0 +1,42 @@
+name = $name;
+ $this->properties = $properties;
+ }
+
+ public function name(): string
+ {
+ return $this->name;
+ }
+
+ /**
+ * @param string $property
+ * @return mixed
+ * @throws \RuntimeException
+ */
+ public function __get(string $property)
+ {
+ if (!array_key_exists($property, $this->properties)) {
+ throw new \RuntimeException(sprintf(
+ 'Property "%s" does not exist on domain event "%s".',
+ $property,
+ $this->name
+ ));
+ }
+
+ return $this->properties[$property];
+ }
+}
diff --git a/src/EventProvider.php b/src/EventProvider.php
new file mode 100644
index 0000000..0e5163e
--- /dev/null
+++ b/src/EventProvider.php
@@ -0,0 +1,10 @@
+events;
+ $this->events = [];
+
+ return $events;
+ }
+
+ /**
+ * @param string|DomainEvent $event
+ * @param array $properties
+ * @throws \InvalidArgumentException
+ */
+ protected function raise($event, array $properties = [])
+ {
+ if (is_string($event)) {
+ $event = new DomainEvent($event, $properties);
+ } elseif (!$event instanceof DomainEvent) {
+ throw new \InvalidArgumentException(sprintf(
+ 'Invalid domain event. Can only raise instances of "%s".',
+ DomainEvent::class
+ ));
+ }
+
+ $this->events[self::$order++] = $event;
+ }
+}
diff --git a/tests/DispatchDomainEventsTest.php b/tests/DispatchDomainEventsTest.php
new file mode 100644
index 0000000..2e4f66f
--- /dev/null
+++ b/tests/DispatchDomainEventsTest.php
@@ -0,0 +1,133 @@
+ [Article::class],
+ ];
+
+ /** @var ArticleListener|\PHPUnit_Framework_MockObject_MockObject */
+ private $articleListenerMock;
+
+ protected function setUp()
+ {
+ $this->useModelSet('article');
+ parent::setUp();
+ $this->articleListenerMock = $this->getMockForAbstractClass(ArticleListener::class);
+ $this->_em->getEventManager()->addEventSubscriber(new DoctrineDomainEventDispatcher);
+ $this->_em->getEventManager()->addEventSubscriber($this->articleListenerMock);
+ }
+
+ function test_domain_event_is_dispatched_on_post_flush()
+ {
+ $article = new Article(__FUNCTION__);
+
+ $this->articleListenerMock
+ ->expects($this->once())
+ ->method(Article::EVENT_ARTICLE_PUBLISHED)
+ ->with(new DomainEvent(Article::EVENT_ARTICLE_PUBLISHED, ['article' => $article]));
+
+ $article->publish();
+ $this->_em->persist($article);
+ $this->_em->flush();
+ }
+
+ function test_domain_event_is_not_dispatched_without_flushing()
+ {
+ $this->articleListenerMock
+ ->expects($this->never())
+ ->method(Article::EVENT_ARTICLE_PUBLISHED);
+
+ $article = new Article(__FUNCTION__);
+ $article->publish();
+ $this->_em->persist($article);
+ }
+
+ function test_domain_events_are_dispatched_on_post_remove()
+ {
+ $article = new Article(__FUNCTION__);
+
+ $this->articleListenerMock
+ ->expects($this->at(0))
+ ->method(Article::EVENT_ARTICLE_PUBLISHED)
+ ->with(new DomainEvent(Article::EVENT_ARTICLE_PUBLISHED, ['article' => $article]));
+ $this->articleListenerMock
+ ->expects($this->at(1))
+ ->method(Article::EVENT_ARTICLE_REMOVED)
+ ->with(new DomainEvent(Article::EVENT_ARTICLE_REMOVED, ['article' => $article]));
+
+ $article->publish();
+ $this->_em->persist($article);
+ $this->_em->flush();
+ $this->_em->remove($article);
+ $this->_em->flush();
+ }
+
+ function test_multiple_domain_events_are_dispatched_on_post_remove()
+ {
+ $firstArticle = new Article('first');
+ $secondArticle = new Article('second');
+
+ $this->articleListenerMock
+ ->expects($this->exactly(2))
+ ->method(Article::EVENT_ARTICLE_REMOVED);
+ $this->articleListenerMock
+ ->expects($this->at(0))
+ ->method(Article::EVENT_ARTICLE_REMOVED)
+ ->with(new DomainEvent(Article::EVENT_ARTICLE_REMOVED, ['article' => $firstArticle]));
+ $this->articleListenerMock
+ ->expects($this->at(1))
+ ->method(Article::EVENT_ARTICLE_REMOVED)
+ ->with(new DomainEvent(Article::EVENT_ARTICLE_REMOVED, ['article' => $secondArticle]));
+
+ $this->_em->persist($firstArticle);
+ $this->_em->persist($secondArticle);
+ $this->_em->flush();
+ $this->_em->remove($firstArticle);
+ $this->_em->remove($secondArticle);
+ $this->_em->flush();
+ }
+
+ function test_domain_events_are_dispatched_in_correct_order()
+ {
+ $firstArticle = new Article('first');
+ $secondArticle = new Article('second');
+
+ $this->articleListenerMock
+ ->expects($this->at(0))
+ ->method(Article::EVENT_ARTICLE_PUBLISHED)
+ ->with(new DomainEvent(Article::EVENT_ARTICLE_PUBLISHED, ['article' => $secondArticle]));
+ $this->articleListenerMock
+ ->expects($this->at(1))
+ ->method(Article::EVENT_ARTICLE_REMOVED)
+ ->with(new DomainEvent(Article::EVENT_ARTICLE_REMOVED, ['article' => $firstArticle]));
+
+ $this->_em->persist($firstArticle);
+ $this->_em->persist($secondArticle);
+ $this->_em->flush();
+ $secondArticle->publish();
+ $this->_em->remove($firstArticle);
+ $this->_em->flush();
+ }
+
+ function test_flushing_inside_flush()
+ {
+ $this->_em->getEventManager()->addEventSubscriber(new EditArticleOnPublish($this->_em, 'content'));
+ $article = new Article(__FUNCTION__);
+ $article->publish();
+ $this->_em->persist($article);
+ $this->_em->flush();
+ $this->assertSame('content', $article->content());
+ $this->_em->refresh($article);
+ $this->assertSame('content', $article->content());
+ }
+}
diff --git a/tests/DomainEventTest.php b/tests/DomainEventTest.php
new file mode 100644
index 0000000..f70d101
--- /dev/null
+++ b/tests/DomainEventTest.php
@@ -0,0 +1,32 @@
+assertSame('name', (new DomainEvent('name'))->name());
+ }
+
+ function test_getting_properties()
+ {
+ $domainEvent = new DomainEvent('name', [
+ 'foo' => 'foo',
+ 'bar' => 'bar',
+ 'baz' => null,
+ ]);
+ $this->assertSame('foo', $domainEvent->foo);
+ $this->assertSame('bar', $domainEvent->bar);
+ $this->assertNull($domainEvent->baz);
+ }
+
+ function test_getting_undefined_property_throws_exception()
+ {
+ $this->expectException(\RuntimeException::class);
+ $this->expectExceptionMessage('Property "foo" does not exist on domain event "name".');
+ $this->assertSame('foo', (new DomainEvent('name'))->foo);
+ }
+}
diff --git a/tests/EventProviderTraitTest.php b/tests/EventProviderTraitTest.php
new file mode 100644
index 0000000..b82ca97
--- /dev/null
+++ b/tests/EventProviderTraitTest.php
@@ -0,0 +1,49 @@
+assertSame([], $eventProvider->popEvents());
+
+ $eventProvider->raise('foo', ['foo' => 'foo']);
+ $eventProvider->raise('bar', ['bar' => 'bar']);
+
+ $domainEvents = [new DomainEvent('foo', ['foo' => 'foo']), new DomainEvent('bar', ['bar' => 'bar'])];
+ $this->assertEquals($domainEvents, $eventProvider->popEvents());
+ $this->assertSame([], $eventProvider->popEvents());
+ }
+
+ function test_order_of_delivery_is_recorded_across_event_providers()
+ {
+ $firstEventProvider = new TestEventProvider;
+ $firstEventProvider->raise(new DomainEvent('name'));
+
+ $secondEventProvider = new TestEventProvider;
+ $secondEventProvider->raise(new DomainEvent('name'));
+
+ $this->assertGreaterThan(key($firstEventProvider->popEvents()), key($secondEventProvider->popEvents()));
+ }
+
+ function test_raising_invalid_event_throws_exception()
+ {
+ $this->expectException(\InvalidArgumentException::class);
+ $this->expectExceptionMessage('Invalid domain event.');
+ $eventProvider = new TestEventProvider;
+ $eventProvider->raise(new \stdClass);
+ }
+}
+
+class TestEventProvider implements EventProvider
+{
+ use EventProviderTrait {
+ raise as public;
+ }
+}
diff --git a/tests/Fixtures/Article.php b/tests/Fixtures/Article.php
new file mode 100644
index 0000000..2ea6792
--- /dev/null
+++ b/tests/Fixtures/Article.php
@@ -0,0 +1,71 @@
+id = $id;
+ }
+
+ public function id(): string
+ {
+ return $this->id;
+ }
+
+ /**
+ * @return string|null
+ */
+ public function content()
+ {
+ return $this->content;
+ }
+
+ public function edit(string $content)
+ {
+ $this->content = $content;
+ }
+
+ public function publish()
+ {
+ $this->raise(self::EVENT_ARTICLE_PUBLISHED, ['article' => $this]);
+ }
+
+ /**
+ * @PostRemove
+ */
+ public function onPostRemove()
+ {
+ $this->raise(self::EVENT_ARTICLE_REMOVED, ['article' => $this]);
+ }
+}
diff --git a/tests/Fixtures/ArticleListener.php b/tests/Fixtures/ArticleListener.php
new file mode 100644
index 0000000..bde4178
--- /dev/null
+++ b/tests/Fixtures/ArticleListener.php
@@ -0,0 +1,17 @@
+entityManager = $entityManager;
+ $this->content = $content;
+ }
+
+ public function onArticlePublish(DomainEvent $event)
+ {
+ $this->editArticle($event->article);
+ }
+
+ public function getSubscribedEvents(): array
+ {
+ return [Article::EVENT_ARTICLE_PUBLISHED];
+ }
+
+ private function editArticle(Article $article)
+ {
+ $article->edit($this->content);
+ $this->entityManager->flush($article);
+ }
+}