commit f3939bbd136c45f7b74cf9857b59f034c0b4dee8 Author: Danyi Dávid Date: Sun Jul 31 20:47:25 2016 +0200 * initial commit diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..fa449f6 --- /dev/null +++ b/.gitignore @@ -0,0 +1,4 @@ +.idea +composer.phar +phpunit.xml +vendor/ diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 0000000..4d90fc8 --- /dev/null +++ b/.travis.yml @@ -0,0 +1,28 @@ +sudo: false + +language: php + +matrix: + fast_finish: true + include: + - php: 5.5 + - php: 5.6 + env: + - EXECUTE_CS_CHECK=true + - php: 7 + - php: hhvm + allow_failures: + - php: hhvm + +before_install: + - composer self-update + +install: + - travis_retry composer install --no-interaction --ignore-platform-reqs --prefer-source --no-scripts + +script: + - composer test + - if [[ $EXECUTE_CS_CHECK == 'true' ]]; then composer cs ; fi + +notifications: + email: true diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..2d6f0c2 --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,526 @@ +# Changelog + +All notable changes to this project will be documented in this file, in reverse chronological order by release. + +## 1.0.2 - 2016-04-21 + +### Added + +- Nothing. + +### Deprecated + +- Nothing. + +### Removed + +- Nothing. + +### Fixed + +- [#85](https://github.com/zendframework/zend-expressive-skeleton/pull/85) + updates the Aura.Di dependency to stable 3.X versions. +- [#88](https://github.com/zendframework/zend-expressive-skeleton/pull/88) + modifies the installer to remove `composer.lock` from the `.gitignore` file + during initial installation. +- [#89](https://github.com/zendframework/zend-expressive-skeleton/pull/89) + updates the zend-stdlib dependency to allow usage of its v3 series. + +## 1.0.1 - 2016-03-17 + +### Added + +- Nothing. + +### Deprecated + +- Nothing. + +### Removed + +- Nothing. + +### Fixed + +- [#53](https://github.com/zendframework/zend-expressive-skeleton/pull/53) + updates the default Pimple container script such that it now caches factory + instances for re-use. +- [#72](https://github.com/zendframework/zend-expressive-skeleton/pull/72) + updates the `composer.json` to remove the possibility of installing an + Expressive RC version, updates zend-servicemanager to allow using 3.0 + versions, and updates whoops to allow either 1.1 or 2.0 versions. +- [#80](https://github.com/zendframework/zend-expressive-skeleton/pull/80) + updates the default ProxyManager constraints to also allow v2 versions. +- [#81](https://github.com/zendframework/zend-expressive-skeleton/pull/81) + fixes an issue in the installer whereby specified constraints were not being + passed to Composer prior to dependency resolution/installation, resulting in + stale dependencies. +- [#78](https://github.com/zendframework/zend-expressive-skeleton/pull/78) + updates the shipped default error templates to remove error/exception display. + Users who really need this functionality can write their own templates; the + project aims to deliver a "safe by default" setting. + +## 1.0.0 - 2016-01-28 + +First stable release. + +### Added + +- Nothing. + +### Deprecated + +- Nothing. + +### Removed + +- Nothing. + +### Fixed + +- [#69](https://github.com/zendframework/zend-expressive-skeleton/pull/69) + updates the links in templates to point to the new documentation site on + https://zendframework.github.io/zend-expressive/ instead of rtfd.org. + +## 1.0.0rc8 - 2016-01-21 + +Eighth release candidate. + +### Added + +- Nothing. + +### Deprecated + +- Nothing. + +### Removed + +- Nothing. + +### Fixed + +- [#66](https://github.com/zendframework/zend-expressive-skeleton/pull/66) + adds the `'error' => true,` declaration to the `'error'` pipeline middleware + specification. +- [#67](https://github.com/zendframework/zend-expressive-skeleton/pull/67) + updates the `filp/whoops` dependency for installer development to `^1.1 || ^2.0`; + the two are compatible for our use cases, but we should prefer the latest + that can be installed. As 2.0 requires PHP 5.5.9, but our minimum PHP version + is 5.5.0, we must specify both. + +## 1.0.0rc7 - 2016-01-19 + +Seventh release candidate. + +### Added + +- Nothing. + +### Deprecated + +- Nothing. + +### Removed + +- Nothing. + +### Fixed + +- [#64](https://github.com/zendframework/zend-expressive-skeleton/pull/64) + fixes the installer script to correctly rewrite the `require-dev` section + and ensure only the development dependencies selected, as well as base + requirements such as PHPUnit and PHP_CodeSniffer, are installed. As such, + the `--no-dev` flag is no longer required, and development dependencies + such as whoops are properly installed. + +## 1.0.0rc6 - 2016-01-19 + +Sixth release candidate. + +### Added + +- Nothing. + +### Deprecated + +- Nothing. + +### Removed + +- Nothing. + +### Fixed + +- [#56](https://github.com/zendframework/zend-expressive-skeleton/pull/56) + updates the `composer serve` command to include the `public/index.php` script + as an argument. This ensures that asset paths that the application could + intercept and serve will be passed to the application (previously, the + built-in server would treat these as 404s, and never pass them to the + application). +- [#57](https://github.com/zendframework/zend-expressive-skeleton/pull/57) + updates the Apache configuration rules defined in `public/.htaccess` to omit + several that could prevent the application from intercepting requests for + assets. +- [#52](https://github.com/zendframework/zend-expressive-skeleton/pull/52) + fixes the switch statement in the `HomePageAction` class to ensure the + template name and documentation link are accurately found. +- [#59](https://github.com/zendframework/zend-expressive-skeleton/pull/59) + updates the `config/container.php` implementation for zend-servicemanager such + that it can work with either v2 or v3 of that library. +- [#60](https://github.com/zendframework/zend-expressive-skeleton/pull/60) + updates the zend-expressive-helpers dependency to `^2.0`, and updates the + `config/autoload/middleware-pipeline.global.php` to follow the changes in + middleware configuration introduced in [zend-expressive #270](https://github.com/zendframework/zend-expressive/pull/270). + The change introduces convention-based keys for "always" (execute before + routing), "routing" (routing, listeners that act on the route result, and + dispatching), and "error", with reasonable priorities to ensure execution + order. +- [#60](https://github.com/zendframework/zend-expressive-skeleton/pull/60) + fixes the documentation for `composer create-project` to include the + `--no-dev` flag; this is done as composer currently installs the development + dependencies listed before the installer script rewrites the `composer.json` + file. Running `composer update` or `composer install` within the project + directory after the initial installation will install the development + dependencies. + +## 1.0.0rc5 - 2015-12-22 + +Fifth release candidate. + +### Added + +- Nothing. + +### Deprecated + +- Nothing. + +### Removed + +- Nothing. + +### Fixed + +- [#42](https://github.com/zendframework/zend-expressive-skeleton/pull/42) + fixes some grammatical issues in the questions presented by the installer. +- [#45](https://github.com/zendframework/zend-expressive-skeleton/pull/45) + fixes how JS and CSS assets are added to zend-view templates. +- [#48](https://github.com/zendframework/zend-expressive-skeleton/pull/48) + adds unit tests for the `OptionalPackages` class (which provides the Composer + installer scripts). +- [#49](https://github.com/zendframework/zend-expressive-skeleton/pull/49) + updates the Pimple support to Pimple v3, ensuring Pimple users are using the + latest stable release. + +## 1.0.0rc4 - 2015-12-09 + +Fourth release candidate. + +### Added + +- [#34](https://github.com/zendframework/zend-expressive-skeleton/pull/34) + updates the zend-view configuration to register a factory for + `Zend\View\HelperPluginManager`, as well as a `view_helpers` sub-key for + registering custom view helpers. +- [#37](https://github.com/zendframework/zend-expressive-skeleton/pull/37) + creates the subdirectories `src/App/` and `test/AppTest/`, moving the + subdirectories of each under those, and updating the `composer.json` + autoloading directives accordingly. This change will allow new projects to + implement a "modular" structure if desired, with a subdirectory per namespace. +- [#41](https://github.com/zendframework/zend-expressive-skeleton/pull/41) adds + the composer script "serve", which fires up the built-in PHP webserver on port + 8080; invoke using `composer serve`. + +### Deprecated + +- Nothing. + +### Removed + +- Nothing. + +### Fixed + +- [#23](https://github.com/zendframework/zend-expressive-skeleton/pull/23) + updates the comment for the glob statements to ensure all 4 (not just 2!) + possible matches are detailed. +- [#24](https://github.com/zendframework/zend-expressive-skeleton/pull/24) + updates the `config/config.php` file to store cached configuration as a plain + PHP file, so that it can simply `include()`; this will be faster than using + JSON-serialized structures. +- [#30](https://github.com/zendframework/zend-expressive-skeleton/pull/30) + updates the Twig configuration to follow the changes made for + [zendframework/zend-expressive-twigrenderer 0.3.0](https://github.com/zendframework/zend-expressive-twigrenderer/releases/tag/0.3.0). + The old configuration format will still work, though users *should* update + their configuration to the new format. The change in this patch only affects + new installs. +- [#33](https://github.com/zendframework/zend-expressive-skeleton/pull/33) + updates to zendframework/zend-expressive-helpers `^1.2`. +- [#33](https://github.com/zendframework/zend-expressive-skeleton/pull/33) adds + configuration for auto-registering the new `Zend\Expressive\Helper\UrlHelperMiddleware` + as pipeline middleware; this fixes an issue when using the zend-view renderer + with the `url()` helper whereby the `UrlHelper` was being registered as a + route result observer too late to receive the `RouteResult`. +- [#40](https://github.com/zendframework/zend-expressive-skeleton/pull/40) + renames the namespace for the installer to `ExpressiveInstaller`. + +## 1.0.0rc3 - 2015-12-07 + +Third release candidate. + +### Added + +- [#20](https://github.com/zendframework/zend-expressive-skeleton/pull/20) adds + the ability to specify a "minimal" install; when selected, the installer will + install modified configuration, omit some files, and remove the default + middleware and public assets. +- [#27](https://github.com/zendframework/zend-expressive-skeleton/pull/27) adds + [zendframework/zend-expressive-helpers](https://github.com/zendframework/zend-expressive-helpers) + as a dependency, and integrates the helpers into the configuration. + +### Deprecated + +- Nothing. + +### Removed + +- Nothing. + +### Fixed + +- [#13](https://github.com/zendframework/zend-expressive-skeleton/pull/13) + updates the installer to also remove the dependency on composer/composer + on completion. +- [#11](https://github.com/zendframework/zend-expressive-skeleton/pull/11) + moves the route middleware service definitions into the routes configuration + files. +- [#21](https://github.com/zendframework/zend-expressive-skeleton/pull/21) + updates `require` statements in generated configuration files to use the + `__DIR__` constant to ensure files are located relative to the origin file. +- [#25](https://github.com/zendframework/zend-expressive-skeleton/pull/25) and + [#29](https://github.com/zendframework/zend-expressive-skeleton/pull/29) + update minimum versions for each router and template implementation (final + versions for RC3 are all at `^1.0`). +- [#29](https://github.com/zendframework/zend-expressive-skeleton/pull/29) sets + the zend-expressive required version to `~1.0.0@rc || ^1.0`, to ensure a + stable version is always installed. + +## 1.0.0rc2 - 2015-10-20 + +Second release candidate. + +### Added + +- Nothing. + +### Deprecated + +- Nothing. + +### Removed + +- Nothing. + +### Fixed + +- Updated expressive to RC2. +- Updated subcomponent versions in installer to `^0.2` + +## 1.0.0rc1 - 2015-10-19 + +First release candidate. + +### Added + +- Nothing. + +### Deprecated + +- Nothing. + +### Removed + +- Nothing. + +### Fixed + +- Nothing. + +## 0.5.3 - 2015-10-16 + +### Added + +- [#8](https://github.com/zendframework/zend-expressive-skeleton/pull/8) adds a + routine to the installer that recursively removes the `src/Composer/` + directory of the skeleton, ensuring you have a clean start when creating a + project. + +### Deprecated + +- Nothing. + +### Removed + +- Nothing. + +### Fixed + +- Nothing. + +## 0.5.2 - 2015-10-13 + +### Added + +- [#7](https://github.com/zendframework/zend-expressive-skeleton/pull/7) adds a + dependency on zend-stdlib for the purposes of globbing and merging + configuration. + +### Deprecated + +- Nothing. + +### Removed + +- Nothing. + +### Fixed + +- Nothing. + +## 0.5.1 - 2015-10-11 + +### Added + +- Nothing. + +### Deprecated + +- Nothing. + +### Removed + +- Nothing. + +### Fixed + +- [#6](https://github.com/zendframework/zend-expressive-skeleton/pull/6) updates + the zendframework/zend-view package configuration to remove the dependency on + zendframework/zend-i18n, as it is now handled in the standalone + zend-expressive-zendviewrenderer package. + +## 0.5.0 - 2015-10-10 + +### Added + +- Nothing. + +### Deprecated + +- Nothing. + +### Removed + +- Nothing. + +### Fixed + +- [#3](https://github.com/zendframework/zend-expressive-skeleton/pull/3) updates + the skeleton to use zendframework/zend-expressive 0.4.0. + +## 0.4.0 - 2015-10-09 + +First release as zend-expressive-skeleton. + +### Added + +- Nothing. + +### Deprecated + +- Nothing. + +### Removed + +- Nothing. + +### Fixed + +- Nothing. + +## 0.3.0 - 2015-09-12 + +### Added + +- Use zend-expressive template factories. +- Use the zend view url helper in the layout template. + +### Deprecated + +- Nothing. + +### Removed + +- Nothing. + +### Fixed + +- Nothing. + +## 0.2.0 - 2015-09-11 + +### Added + +- [#bbb2e60](https://github.com/xtreamwayz/expressive-composer-installer/commit/bbb2e607af23e3ae23f6a9c71eb97c3c651c0ca1) adds PHPUnit tests. +- [#791c1c6](https://github.com/xtreamwayz/expressive-composer-installer/commit/791c1c63f324ca08d08e26375f3a356102bf2ad9) adds Whoops error handler. +- [e1d8d7bf](https://github.com/xtreamwayz/expressive-composer-installer/commit/e1d8d7bf5d5e2f51863fa59a37d1963405743201) adds config caching in production mode. + +### Deprecated + +- Nothing. + +### Removed + +- Nothing. + +### Fixed + +- Nothing. + +## 0.1.1 - 2015-09-08 + +### Added + +- [#b4a0923](https://github.com/xtreamwayz/expressive-composer-installer/commit/b4a092386993227f8057d7ad4e0d9762659eefb0) adds support for Pimple 3.0.x. Still needs testing! + +### Deprecated + +- Nothing. + +### Removed + +- Nothing. + +### Fixed + +- [#11](https://github.com/xtreamwayz/expressive-composer-installer/issues/11) fixes an issues where non stable packages are not being installed correctly. + +## 0.1.0 - 2015-09-07 + +Initial tagged release. + +### Added + +- Everything. + +### Deprecated + +- Nothing. + +### Removed + +- Nothing. + +### Fixed + +- Nothing. diff --git a/CONDUCT.md b/CONDUCT.md new file mode 100644 index 0000000..c663d2b --- /dev/null +++ b/CONDUCT.md @@ -0,0 +1,43 @@ +# Contributor Code of Conduct + +The Zend Framework project adheres to [The Code Manifesto](http://codemanifesto.com) +as its guidelines for contributor interactions. + +## The Code Manifesto + +We want to work in an ecosystem that empowers developers to reach their +potential — one that encourages growth and effective collaboration. A space that +is safe for all. + +A space such as this benefits everyone that participates in it. It encourages +new developers to enter our field. It is through discussion and collaboration +that we grow, and through growth that we improve. + +In the effort to create such a place, we hold to these values: + +1. **Discrimination limits us.** This includes discrimination on the basis of + race, gender, sexual orientation, gender identity, age, nationality, technology + and any other arbitrary exclusion of a group of people. +2. **Boundaries honor us.** Your comfort levels are not everyone’s comfort + levels. Remember that, and if brought to your attention, heed it. +3. **We are our biggest assets.** None of us were born masters of our trade. + Each of us has been helped along the way. Return that favor, when and where + you can. +4. **We are resources for the future.** As an extension of #3, share what you + know. Make yourself a resource to help those that come after you. +5. **Respect defines us.** Treat others as you wish to be treated. Make your + discussions, criticisms and debates from a position of respectfulness. Ask + yourself, is it true? Is it necessary? Is it constructive? Anything less is + unacceptable. +6. **Reactions require grace.** Angry responses are valid, but abusive language + and vindictive actions are toxic. When something happens that offends you, + handle it assertively, but be respectful. Escalate reasonably, and try to + allow the offender an opportunity to explain themselves, and possibly correct + the issue. +7. **Opinions are just that: opinions.** Each and every one of us, due to our + background and upbringing, have varying opinions. The fact of the matter, is + that is perfectly acceptable. Remember this: if you respect your own + opinions, you should respect the opinions of others. +8. **To err is human.** You might not intend it, but mistakes do happen and + contribute to build experience. Tolerate honest mistakes, and don't hesitate + to apologize if you make one yourself. diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 0000000..b6e2158 --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,233 @@ +# CONTRIBUTING + +## RESOURCES + +If you wish to contribute to Zend Framework, please be sure to +read/subscribe to the following resources: + + - [Coding Standards](https://github.com/zendframework/zf2/wiki/Coding-Standards) + - [Contributor's Guide](CONTRIBUTING.md) + - ZF Contributor's mailing list: + Archives: http://zend-framework-community.634137.n4.nabble.com/ZF-Contributor-f680267.html + Subscribe: zf-contributors-subscribe@lists.zend.com + - ZF Contributor's IRC channel: + #zftalk.dev on Freenode.net + +If you are working on new features or refactoring [create a proposal](https://github.com/zendframework/zend-expressive-skeleton/issues/new). + +## Reporting Potential Security Issues + +If you have encountered a potential security vulnerability, please **DO NOT** report it on the public +issue tracker: send it to us at [zf-security@zend.com](mailto:zf-security@zend.com) instead. +We will work with you to verify the vulnerability and patch it as soon as possible. + +When reporting issues, please provide the following information: + +- Component(s) affected +- A description indicating how to reproduce the issue +- A summary of the security vulnerability and impact + +We request that you contact us via the email address above and give the project +contributors a chance to resolve the vulnerability and issue a new release prior +to any public exposure; this helps protect users and provides them with a chance +to upgrade and/or update in order to protect their applications. + +For sensitive email communications, please use [our PGP key](http://framework.zend.com/zf-security-pgp-key.asc). + +## RUNNING TESTS + +To run tests: + +- Clone the repository: + + ```console + $ git clone git@github.com:zendframework/zend-expressive-skeleton.git + $ cd zend-expressive-skeleton + ``` + +- Install dependencies via composer: + + ```console + $ composer install + ``` + + **NOTE:** If you are wanting to test the installer itself, add the + `--no-scripts` flag to the `composer install` command. + + If you don't have `curl` installed, you can also download `composer.phar` from + https://getcomposer.org/: + + ```console + $ curl -sS https://getcomposer.org/installer | php -- + $ ln -s composer.phar composer + ``` + +- Run the tests using the "test" command shipped in the `composer.json`: + + ```console + $ composer test + ``` + +You can turn on conditional tests with the `phpunit.xml` file. +To do so: + + - Copy `phpunit.xml.dist` file to `phpunit.xml` + - Edit `phpunit.xml` to enable any specific functionality you + want to test, as well as to provide test values to utilize. + +## Running Coding Standards Checks + +First, ensure you've installed dependencies via composer, per the previous +section on running tests. + +To run CS checks only: + +```console +$ composer cs +``` + +To attempt to automatically fix common CS issues: + + +```console +$ composer cs-fix +``` + +If the above fixes any CS issues, please re-run the tests to ensure +they pass, and make sure you add and commit the changes after verification. + +## Recommended Workflow for Contributions + +Your first step is to establish a public repository from which we can +pull your work into the master repository. We recommend using +[GitHub](https://github.com), as that is where the component is already hosted. + +1. Setup a [GitHub account](http://github.com/), if you haven't yet +2. Fork the repository (http://github.com/zendframework/zend-expressive-skeleton) +3. Clone the canonical repository locally and enter it. + + ```console + $ git clone git://github.com:zendframework/zend-expressive-skeleton.git + $ cd zend-expressive-skeleton + ``` + +4. Add a remote to your fork; substitute your GitHub username in the command + below. + + ```console + $ git remote add {username} git@github.com:{username}/zend-expressive-skeleton.git + $ git fetch {username} + ``` + +### Keeping Up-to-Date + +Periodically, you should update your fork or personal repository to +match the canonical ZF repository. Assuming you have setup your local repository +per the instructions above, you can do the following: + + +```console +$ git checkout master +$ git fetch origin +$ git rebase origin/master +# OPTIONALLY, to keep your remote up-to-date - +$ git push {username} master:master +``` + +If you're tracking other branches -- for example, the "develop" branch, where +new feature development occurs -- you'll want to do the same operations for that +branch; simply substitute "develop" for "master". + +### Working on a patch + +We recommend you do each new feature or bugfix in a new branch. This simplifies +the task of code review as well as the task of merging your changes into the +canonical repository. + +A typical workflow will then consist of the following: + +1. Create a new local branch based off either your master or develop branch. +2. Switch to your new local branch. (This step can be combined with the + previous step with the use of `git checkout -b`.) +3. Do some work, commit, repeat as necessary. +4. Push the local branch to your remote repository. +5. Send a pull request. + +The mechanics of this process are actually quite trivial. Below, we will +create a branch for fixing an issue in the tracker. + +```console +$ git checkout -b hotfix/9295 +Switched to a new branch 'hotfix/9295' +``` + +... do some work ... + + +```console +$ git commit +``` + +... write your log message ... + + +```console +$ git push {username} hotfix/9295:hotfix/9295 +Counting objects: 38, done. +Delta compression using up to 2 threads. +Compression objects: 100% (18/18), done. +Writing objects: 100% (20/20), 8.19KiB, done. +Total 20 (delta 12), reused 0 (delta 0) +To ssh://git@github.com/{username}/zend-expressive-skeleton.git + b5583aa..4f51698 HEAD -> master +``` + +To send a pull request, you have two options. + +If using GitHub, you can do the pull request from there. Navigate to +your repository, select the branch you just created, and then select the +"Pull Request" button in the upper right. Select the user/organization +"zendframework" as the recipient. + +If using your own repository - or even if using GitHub - you can use `git +format-patch` to create a patchset for us to apply; in fact, this is +**recommended** for security-related patches. If you use `format-patch`, please +send the patches as attachments to: + +- zf-devteam@zend.com for patches without security implications +- zf-security@zend.com for security patches + +#### What branch to issue the pull request against? + +Which branch should you issue a pull request against? + +- For fixes against the stable release, issue the pull request against the + "master" branch. +- For new features, or fixes that introduce new elements to the public API (such + as new public methods or properties), issue the pull request against the + "develop" branch. + +### Branch Cleanup + +As you might imagine, if you are a frequent contributor, you'll start to +get a ton of branches both locally and on your remote. + +Once you know that your changes have been accepted to the master +repository, we suggest doing some cleanup of these branches. + +- Local branch cleanup + + ```console + $ git branch -d + ``` + +- Remote branch removal + + ```console + $ git push {username} : + ``` + + +## Conduct + +Please see our [CONDUCT.md](CONDUCT.md) to understand expected behavior when interacting with others in the project. diff --git a/LICENSE.md b/LICENSE.md new file mode 100644 index 0000000..b401e72 --- /dev/null +++ b/LICENSE.md @@ -0,0 +1,12 @@ +Copyright (c) 2015, Zend Technologies USA, Inc. +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + +- Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. + +- Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. + +- Neither the name of Zend Technologies USA, Inc. nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/README.md b/README.md new file mode 100644 index 0000000..1966b14 --- /dev/null +++ b/README.md @@ -0,0 +1,88 @@ +# Expressive Skeleton and Installer + +[![Build Status](https://secure.travis-ci.org/zendframework/zend-expressive-skeleton.svg?branch=master)](https://secure.travis-ci.org/zendframework/zend-expressive-skeleton) + +*Begin developing PSR-7 middleware applications in seconds!* + +[zend-expressive](https://github.com/zendframework/zend-expressive) builds on +[zend-stratigility](https://github.com/zendframework/zend-stratigility) to +provide a minimalist PSR-7 middleware framework for PHP with routing, DI +container, optional templating, and optional error handling capabilities. + +This installer will setup a skeleton application based on zend-expressive by +choosing optional packages based on user input as demonstrated in the following +screenshot: + +![screenshot-installer](https://cloud.githubusercontent.com/assets/459648/10410494/16bdc674-6f6d-11e5-8190-3c1466e93361.png) + +The user selected packages are saved into `composer.json` so that everyone else +working on the project have the same packages installed. Configuration files and +templates are prepared for first use. The installer command is removed from +`composer.json` after setup succeeded, and all installer related files are +removed. + +## Getting Started + +Start your new Expressive project with composer: + +```bash +$ composer create-project zendframework/zend-expressive-skeleton +``` + +After choosing and installing the packages you want, go to the +`` and start PHP's built-in web server to verify installation: + +```bash +$ composer serve +``` + +You can then browse to http://localhost:8080. + +> ### Setting a timeout +> +> Composer commands time out after 300 seconds (5 minutes). On Linux-based +> systems, the `php -S` command that `composer server` spawns continues running +> as a background process, but on other systems halts when the timeout occurs. +> +> If you want the server to live longer, you can use the +> `COMPOSER_PROCESS_TIMEOUT` environment variable when executing `composer +> serve` to extend the timeout. As an example, the following will extend it +> to a full day: +> +> ```bash +> $ COMPOSER_PROCESS_TIMEOUT=86400 composer serve +> ``` + +## Troubleshooting + +If the installer fails during the ``composer create-project`` phase, please go +through the following list before opening a new issue. Most issues we have seen +so far can be solved by `self-update` and `clear-cache`. + +1. Be sure to work with the latest version of composer by running `composer self-update`. +2. Try clearing Composer's cache by running `composer clear-cache`. + +If neither of the above help, you might face more serious issues: + +- Info about the [zlib_decode error](https://github.com/composer/composer/issues/4121). +- Info and solutions for [composer degraded mode](https://getcomposer.org/doc/articles/troubleshooting.md#degraded-mode). + +## Skeleton Development + +This section applies only if you cloned this repo with `git clone`, not when you +installed expressive with `composer create-project ...`. + +If you want to run tests against the installer, you need to clone this repo and +setup all dependencies with composer. Make sure you **prevent composer running +scripts** with `--no-scripts`, otherwise it will remove the installer and all +tests. + +```bash +$ composer install --no-scripts +$ composer test +``` + +Please note that the installer tests remove installed config files and templates +before and after running the tests. + +Before contributing read [the contributing guide](CONTRIBUTING.md). diff --git a/cli-config.php b/cli-config.php new file mode 100644 index 0000000..b555030 --- /dev/null +++ b/cli-config.php @@ -0,0 +1,9 @@ + new \Doctrine\ORM\Tools\Console\Helper\EntityManagerHelper( + $container->get('doctrine.entity_manager.orm_default') + ), +]); \ No newline at end of file diff --git a/composer.json b/composer.json new file mode 100644 index 0000000..fd7aea6 --- /dev/null +++ b/composer.json @@ -0,0 +1,58 @@ +{ + "name": "zendframework/zend-expressive-skeleton", + "description": "Zend expressive skelton. Begin developing PSR-7 middleware applications in seconds", + "type": "project", + "homepage": "https://github.com/zendframework/zend-expressive-skeleton", + "license": "BSD-3-Clause", + "authors": [ + { + "name": "Geert Eltink", + "homepage": "https://xtreamwayz.com/" + } + ], + "extra": { + "branch-alias": { + "dev-master": "1.0-dev", + "dev-develop": "1.1-dev" + } + }, + "require": { + "php": "^5.5 || ^7.0", + "roave/security-advisories": "dev-master", + "zendframework/zend-expressive": "^1.0", + "zendframework/zend-expressive-helpers": "^2.0", + "zendframework/zend-stdlib": "^2.7 || ^3.0", + "zendframework/zend-expressive-fastroute": "^1.0", + "zendframework/zend-servicemanager": "^2.7.3 || ^3.0", + "ocramius/proxy-manager": "^1.0 || ^2.0", + "dasprid/container-interop-doctrine": "^0.2.2", + "zendframework/zend-json": "^3.0", + "zendframework/zend-hydrator": "^2.2", + "zendframework/zend-filter": "^2.7" + }, + "require-dev": { + "phpunit/phpunit": "^4.8", + "squizlabs/php_codesniffer": "^2.3", + "filp/whoops": "^1.1 || ^2.0" + }, + "autoload": { + "psr-4": { + "App\\": "src/App/" + } + }, + "autoload-dev": { + "psr-4": { + "AppTest\\": "test/AppTest/" + } + }, + "scripts": { + "check": [ + "@cs", + "@test" + ], + "cs": "phpcs", + "cs-fix": "phpcbf", + "serve": "php -S 0.0.0.0:8080 -t public/ public/index.php", + "test": "phpunit" + } +} diff --git a/composer.lock b/composer.lock new file mode 100644 index 0000000..da34e8b --- /dev/null +++ b/composer.lock @@ -0,0 +1,3128 @@ +{ + "_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": "5c501c2a58fad6e15748d745cfb6789f", + "content-hash": "0c2e0d87469715ccc6b6eed569620cae", + "packages": [ + { + "name": "container-interop/container-interop", + "version": "1.1.0", + "source": { + "type": "git", + "url": "https://github.com/container-interop/container-interop.git", + "reference": "fc08354828f8fd3245f77a66b9e23a6bca48297e" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/container-interop/container-interop/zipball/fc08354828f8fd3245f77a66b9e23a6bca48297e", + "reference": "fc08354828f8fd3245f77a66b9e23a6bca48297e", + "shasum": "" + }, + "type": "library", + "autoload": { + "psr-4": { + "Interop\\Container\\": "src/Interop/Container/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "Promoting the interoperability of container objects (DIC, SL, etc.)", + "time": "2014-12-30 15:22:37" + }, + { + "name": "dasprid/container-interop-doctrine", + "version": "0.2.2", + "source": { + "type": "git", + "url": "https://github.com/DASPRiD/container-interop-doctrine.git", + "reference": "bb1aef96d191be109c6c40c6efc9f8f3f4a1d966" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/DASPRiD/container-interop-doctrine/zipball/bb1aef96d191be109c6c40c6efc9f8f3f4a1d966", + "reference": "bb1aef96d191be109c6c40c6efc9f8f3f4a1d966", + "shasum": "" + }, + "require": { + "container-interop/container-interop": "^1.1", + "doctrine/common": "^2.6", + "doctrine/dbal": "^2.5", + "doctrine/orm": "^2.5", + "php": "^5.5|^7.0" + }, + "require-dev": { + "phpunit/phpunit": "^4.8", + "squizlabs/php_codesniffer": "^2.5" + }, + "type": "library", + "autoload": { + "psr-4": { + "ContainerInteropDoctrine\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-2-Clause" + ], + "description": "Doctrine factories for container-interop", + "homepage": "https://github.com/DASPRiD/container-interop-doctrine", + "time": "2016-03-03 09:59:32" + }, + { + "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.4", + "source": { + "type": "git", + "url": "https://github.com/doctrine/dbal.git", + "reference": "abbdfd1cff43a7b99d027af3be709bc8fc7d4769" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/doctrine/dbal/zipball/abbdfd1cff43a7b99d027af3be709bc8fc7d4769", + "reference": "abbdfd1cff43a7b99d027af3be709bc8fc7d4769", + "shasum": "" + }, + "require": { + "doctrine/common": ">=2.4,<2.7-dev", + "php": ">=5.3.2" + }, + "require-dev": { + "phpunit/phpunit": "4.*", + "symfony/console": "2.*" + }, + "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-01-05 22:11:12" + }, + { + "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": "v2.5.4", + "source": { + "type": "git", + "url": "https://github.com/doctrine/doctrine2.git", + "reference": "bc4ddbfb0114cb33438cc811c9a740d8aa304aab" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/doctrine/doctrine2/zipball/bc4ddbfb0114cb33438cc811c9a740d8aa304aab", + "reference": "bc4ddbfb0114cb33438cc811c9a740d8aa304aab", + "shasum": "" + }, + "require": { + "doctrine/cache": "~1.4", + "doctrine/collections": "~1.2", + "doctrine/common": ">=2.5-dev,<2.7-dev", + "doctrine/dbal": ">=2.5-dev,<2.6-dev", + "doctrine/instantiator": "~1.0.1", + "ext-pdo": "*", + "php": ">=5.4", + "symfony/console": "~2.5|~3.0" + }, + "require-dev": { + "phpunit/phpunit": "~4.0", + "symfony/yaml": "~2.3|~3.0" + }, + "suggest": { + "symfony/yaml": "If you want to use YAML Metadata Mapping Driver" + }, + "bin": [ + "bin/doctrine", + "bin/doctrine.php" + ], + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.6.x-dev" + } + }, + "autoload": { + "psr-0": { + "Doctrine\\ORM\\": "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": "Object-Relational-Mapper for PHP", + "homepage": "http://www.doctrine-project.org", + "keywords": [ + "database", + "orm" + ], + "time": "2016-01-05 21:34:58" + }, + { + "name": "nikic/fast-route", + "version": "v1.0.1", + "source": { + "type": "git", + "url": "https://github.com/nikic/FastRoute.git", + "reference": "8ea928195fa9b907f0d6e48312d323c1a13cc2af" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/nikic/FastRoute/zipball/8ea928195fa9b907f0d6e48312d323c1a13cc2af", + "reference": "8ea928195fa9b907f0d6e48312d323c1a13cc2af", + "shasum": "" + }, + "require": { + "php": ">=5.4.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "FastRoute\\": "src/" + }, + "files": [ + "src/functions.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Nikita Popov", + "email": "nikic@php.net" + } + ], + "description": "Fast request router for PHP", + "keywords": [ + "router", + "routing" + ], + "time": "2016-06-12 19:08:51" + }, + { + "name": "ocramius/package-versions", + "version": "1.1.1", + "source": { + "type": "git", + "url": "https://github.com/Ocramius/PackageVersions.git", + "reference": "4b2bfc8128db95b533303942b0d5b332bffa07c6" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/Ocramius/PackageVersions/zipball/4b2bfc8128db95b533303942b0d5b332bffa07c6", + "reference": "4b2bfc8128db95b533303942b0d5b332bffa07c6", + "shasum": "" + }, + "require": { + "composer-plugin-api": "^1.0", + "php": "~7.0" + }, + "require-dev": { + "composer/composer": "^1.2.0", + "phpunit/phpunit": "^5.4.7" + }, + "type": "composer-plugin", + "extra": { + "class": "PackageVersions\\Installer", + "branch-alias": { + "dev-master": "2.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "PackageVersions\\": "src/PackageVersions" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Marco Pivetta", + "email": "ocramius@gmail.com" + } + ], + "description": "Composer plugin that provides efficient querying for installed package versions (no runtime IO)", + "time": "2016-07-25 07:13:56" + }, + { + "name": "ocramius/proxy-manager", + "version": "2.0.3", + "source": { + "type": "git", + "url": "https://github.com/Ocramius/ProxyManager.git", + "reference": "51c7fdd99dba53808aaab21b34f7a55b302c160c" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/Ocramius/ProxyManager/zipball/51c7fdd99dba53808aaab21b34f7a55b302c160c", + "reference": "51c7fdd99dba53808aaab21b34f7a55b302c160c", + "shasum": "" + }, + "require": { + "ocramius/package-versions": "^1.0", + "php": "7.0.0 - 7.0.5 || ^7.0.7", + "zendframework/zend-code": "3.0.0 - 3.0.2 || ^3.0.4" + }, + "require-dev": { + "couscous/couscous": "^1.4.0", + "ext-phar": "*", + "phpunit/phpunit": "^5.3.4", + "squizlabs/php_codesniffer": "^2.6.0" + }, + "suggest": { + "ocramius/generated-hydrator": "To have very fast object to array to object conversion for ghost objects", + "zendframework/zend-json": "To have the JsonRpc adapter (Remote Object feature)", + "zendframework/zend-soap": "To have the Soap adapter (Remote Object feature)", + "zendframework/zend-xmlrpc": "To have the XmlRpc adapter (Remote Object feature)" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.0.x-dev" + } + }, + "autoload": { + "psr-0": { + "ProxyManager\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Marco Pivetta", + "email": "ocramius@gmail.com", + "homepage": "http://ocramius.github.io/" + } + ], + "description": "A library providing utilities to generate, instantiate and generally operate with Object Proxies", + "homepage": "https://github.com/Ocramius/ProxyManager", + "keywords": [ + "aop", + "lazy loading", + "proxy", + "proxy pattern", + "service proxies" + ], + "time": "2016-07-01 12:11:54" + }, + { + "name": "psr/http-message", + "version": "1.0", + "source": { + "type": "git", + "url": "https://github.com/php-fig/http-message.git", + "reference": "85d63699f0dbedb190bbd4b0d2b9dc707ea4c298" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/http-message/zipball/85d63699f0dbedb190bbd4b0d2b9dc707ea4c298", + "reference": "85d63699f0dbedb190bbd4b0d2b9dc707ea4c298", + "shasum": "" + }, + "require": { + "php": ">=5.3.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\Http\\Message\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "http://www.php-fig.org/" + } + ], + "description": "Common interface for HTTP messages", + "keywords": [ + "http", + "http-message", + "psr", + "psr-7", + "request", + "response" + ], + "time": "2015-05-04 20:22:00" + }, + { + "name": "roave/security-advisories", + "version": "dev-master", + "source": { + "type": "git", + "url": "https://github.com/Roave/SecurityAdvisories.git", + "reference": "d954a95c1be04118dbbda88f3524424695dd886f" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/Roave/SecurityAdvisories/zipball/d954a95c1be04118dbbda88f3524424695dd886f", + "reference": "d954a95c1be04118dbbda88f3524424695dd886f", + "shasum": "" + }, + "conflict": { + "amphp/artax": ">=2,<2.0.4|>0.7.1,<1.0.4", + "aws/aws-sdk-php": ">=3,<3.2.1", + "bugsnag/bugsnag-laravel": ">=2,<2.0.2", + "cakephp/cakephp": ">=3,<3.0.15|>=2,<2.4.99|>=2.5,<2.5.90|>=2.6,<2.6.12|>=1.3,<1.3.18|>=2.7,<2.7.6|>=3.1,<3.1.3", + "codeigniter/framework": "<3.0.3", + "composer/composer": "<=1.0.0-alpha11", + "contao-components/mediaelement": ">=2.14.2,<2.21.1", + "contao/core": ">=2.11,<3|>=3,<3.5.15", + "doctrine/annotations": ">=1,<1.2.7", + "doctrine/cache": ">=1,<1.3.2|>=1.4,<1.4.2", + "doctrine/common": ">=2,<2.4.3|>=2.5,<2.5.1", + "doctrine/dbal": ">=2,<2.0.8|>=2.1,<2.1.2", + "doctrine/doctrine-bundle": "<1.5.2", + "doctrine/doctrine-module": "<=0.7.1", + "doctrine/mongodb-odm": ">=1,<1.0.2", + "doctrine/mongodb-odm-bundle": ">=2,<3.0.1", + "doctrine/orm": ">=2,<2.4.8|>=2.5,<2.5.1", + "dompdf/dompdf": ">=0.6,<0.6.2", + "drupal/core": ">=8,<8.1|>=8.1,<8.1.7", + "drupal/drupal": ">=8,<8.1|>=8.1,<8.1.7", + "firebase/php-jwt": "<2", + "friendsofsymfony/rest-bundle": ">=1.2,<1.2.2", + "friendsofsymfony/user-bundle": ">=1.2,<1.3|>=1.3,<1.3.5", + "guzzlehttp/guzzle": ">=6,<6.2.1|>=4.0.0-rc2,<4.2.4|>=5,<5.3.1", + "illuminate/auth": ">=4,<4.0.99|>=4.1,<4.1.26", + "illuminate/database": ">=4,<4.0.99|>=4.1,<4.1.29", + "joomla/session": "<1.3.1", + "laravel/framework": ">=4,<4.0.99|>=4.1,<4.1.29", + "laravel/socialite": ">=1,<1.0.99|>=2,<2.0.10", + "magento/magento2ce": ">=2,<2.1|>=2.1,<2.2", + "monolog/monolog": ">=1.8,<1.12", + "namshi/jose": "<2.2", + "oro/crm": ">=1.7,<1.7.4", + "oro/platform": ">=1.7,<1.7.4", + "phpmailer/phpmailer": ">=5,<5.2.14", + "pusher/pusher-php-server": "<2.2.1", + "sabre/dav": ">=1.6,<1.6.99|>=1.7,<1.7.11|>=1.8,<1.8.9", + "shopware/shopware": "<4.3.7|>=5,<5.1|>=5.1,<5.1.5", + "silverstripe/cms": ">=3.1,<3.1.11|>=3,<=3.0.11", + "silverstripe/forum": "<=0.6.1|>=0.7,<=0.7.3", + "silverstripe/framework": ">=3,<3.1|>=3.1,<3.2|>=3.2,<3.3", + "silverstripe/userforms": "<3", + "simplesamlphp/simplesamlphp": "<1.14.4", + "socalnick/scn-social-auth": "<1.15.2", + "swiftmailer/swiftmailer": ">=4,<4.99.99|>=5,<5.2.1", + "symfony/dependency-injection": ">=2,<2.0.17", + "symfony/form": ">=2.3,<2.3.35|>=2.4,<2.5|>=2.5,<2.6|>=2.6,<2.6.12|>=2.7,<2.7.7", + "symfony/framework-bundle": ">=2,<2.1|>=2.1,<2.2|>=2.2,<2.3|>=2.3,<2.3.18|>=2.4,<2.4.8|>=2.5,<2.5.2", + "symfony/http-foundation": ">=2,<2.1|>=2.1,<2.2|>=2.2,<2.3|>=2.3,<2.3.27|>=2.4,<2.5|>=2.5,<2.5.11|>=2.6,<2.6.6", + "symfony/http-kernel": ">=2,<2.1|>=2.1,<2.2|>=2.2,<2.3|>=2.3,<2.3.29|>=2.4,<2.5|>=2.5,<2.5.12|>=2.6,<2.6.8", + "symfony/routing": ">=2,<2.0.19", + "symfony/security": ">=2.3,<2.3.37|>=2.4,<2.5|>=2.5,<2.6|>=2.6,<2.6.13|>=2.7,<2.7.9|>=2,<2.0.25|>=2.1,<2.1.13|>=2.2,<2.2.9", + "symfony/security-core": ">=2.8,<2.8.6|>=3,<3.0.6|>=2.4,<2.5|>=2.5,<2.6|>=2.6,<2.6.13|>=2.7,<2.7.9", + "symfony/security-http": ">=2.4,<2.5|>=2.5,<2.6|>=2.6,<2.7|>=2.7,<2.7.13|>=2.3,<2.3.41|>=2.8,<2.8.6|>=3,<3.0.6", + "symfony/serializer": ">=2,<2.0.11", + "symfony/symfony": ">=2,<2.1|>=2.1,<2.2|>=2.2,<2.3|>=2.3,<2.3.41|>=2.4,<2.5|>=2.5,<2.6|>=2.6,<2.7|>=2.7,<2.7.13|>=2.8,<2.8.6|>=3,<3.0.6", + "symfony/translation": ">=2,<2.0.17", + "symfony/validator": ">=2,<2.0.24|>=2.1,<2.1.12|>=2.2,<2.2.5|>=2.3,<2.3.3", + "symfony/web-profiler-bundle": ">=2,<2.1|>=2.1,<2.2|>=2.2,<2.3|>=2.3,<2.3.19|>=2.4,<2.4.9|>=2.5,<2.5.4", + "symfony/yaml": ">=2,<2.0.22|>=2.1,<2.1.7", + "thelia/backoffice-default-template": ">=2.1,<2.1.2", + "thelia/thelia": ">=2.1.0-beta1,<2.1.3|>=2.1,<2.1.2", + "twig/twig": "<1.20", + "typo3/cms": ">=6.2,<6.2.26|>=8,<8.2|>=8.2,<8.2.1|>=7.6,<7.6.10|>=7,<7.1|>=7.1,<7.2|>=7.2,<7.3|>=7.3,<7.4|>=7.4,<7.5|>=7.5,<7.6", + "typo3/flow": ">=1,<1.0.4|>=1.1,<1.1.1|>=2,<2.0.1|>=2.3,<2.3.7|>=3,<3.0.1", + "typo3/neos": ">=1.1,<1.1.3|>=1.2,<1.2.13|>=2,<2.0.4", + "willdurand/js-translation-bundle": "<2.1.1", + "yiisoft/yii": ">=1.1.14,<1.1.15", + "yiisoft/yii2": "<2.0.5", + "yiisoft/yii2-bootstrap": "<2.0.4", + "yiisoft/yii2-dev": "<2.0.4", + "yiisoft/yii2-gii": "<2.0.4", + "yiisoft/yii2-jui": "<2.0.4", + "zendframework/zend-cache": ">=2.4,<2.4.8|>=2.5,<2.5.3", + "zendframework/zend-captcha": ">=2,<2.4.9|>=2.5,<2.5.2", + "zendframework/zend-crypt": ">=2,<2.4.9|>=2.5,<2.5.2", + "zendframework/zend-db": ">=2,<2.0.99|>=2.1,<2.1.99|>=2.2,<2.2.10|>=2.3,<2.3.5", + "zendframework/zend-diactoros": ">=1,<1.0.4", + "zendframework/zend-form": ">=2,<2.2.7|>=2.3,<2.3.1", + "zendframework/zend-http": ">=2,<2.0.99|>=2.1,<2.1.99|>=2.3,<2.3.8|>=2.4,<2.4.1", + "zendframework/zend-json": ">=2.1,<2.1.6|>=2.2,<2.2.6", + "zendframework/zend-ldap": ">=2,<2.0.99|>=2.1,<2.1.99|>=2.2,<2.2.8|>=2.3,<2.3.3", + "zendframework/zend-mail": ">=2,<2.0.99|>=2.1,<2.1.99|>=2.3,<2.3.8|>=2.4,<2.4.1", + "zendframework/zend-navigation": ">=2,<2.2.7|>=2.3,<2.3.1", + "zendframework/zend-session": ">=2,<2.0.99|>=2.1,<2.1.99|>=2.2,<2.2.9|>=2.3,<2.3.4", + "zendframework/zend-validator": ">=2.3,<2.3.6", + "zendframework/zend-view": ">=2,<2.2.7|>=2.3,<2.3.1", + "zendframework/zend-xmlrpc": ">=2.1,<2.1.6|>=2.2,<2.2.6", + "zendframework/zendframework": ">=2,<2.4.9|>=2.5,<2.5.1", + "zendframework/zendframework1": "<1.12.19", + "zendframework/zendopenid": ">=2,<2.0.2", + "zendframework/zendxml": ">=1,<1.0.1", + "zf-commons/zfc-user": "<1.2.2", + "zfcampus/zf-apigility-doctrine": ">=1,<1.0.3", + "zfr/zfr-oauth2-server-module": "<0.1.2" + }, + "type": "metapackage", + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Marco Pivetta", + "email": "ocramius@gmail.com", + "role": "maintainer" + } + ], + "description": "Prevents installation of composer packages with known security vulnerabilities: no API, simply require it", + "time": "2016-07-29 12:29:36" + }, + { + "name": "symfony/console", + "version": "v3.1.3", + "source": { + "type": "git", + "url": "https://github.com/symfony/console.git", + "reference": "f9e638e8149e9e41b570ff092f8007c477ef0ce5" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/console/zipball/f9e638e8149e9e41b570ff092f8007c477ef0ce5", + "reference": "f9e638e8149e9e41b570ff092f8007c477ef0ce5", + "shasum": "" + }, + "require": { + "php": ">=5.5.9", + "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-07-26 08:04:17" + }, + { + "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": "zendframework/zend-code", + "version": "3.0.4", + "source": { + "type": "git", + "url": "https://github.com/zendframework/zend-code.git", + "reference": "c5272131d3acb0f470a2462ed088fca3b6ba61c2" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/zendframework/zend-code/zipball/c5272131d3acb0f470a2462ed088fca3b6ba61c2", + "reference": "c5272131d3acb0f470a2462ed088fca3b6ba61c2", + "shasum": "" + }, + "require": { + "php": "^5.5 || 7.0.0 - 7.0.4 || ^7.0.6", + "zendframework/zend-eventmanager": "^2.6 || ^3.0" + }, + "require-dev": { + "doctrine/annotations": "~1.0", + "ext-phar": "*", + "phpunit/phpunit": "^4.8.21", + "squizlabs/php_codesniffer": "^2.5", + "zendframework/zend-stdlib": "^2.7 || ^3.0" + }, + "suggest": { + "doctrine/annotations": "Doctrine\\Common\\Annotations >=1.0 for annotation features", + "zendframework/zend-stdlib": "Zend\\Stdlib component" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.0-dev", + "dev-develop": "3.1-dev" + } + }, + "autoload": { + "psr-4": { + "Zend\\Code\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "description": "provides facilities to generate arbitrary code using an object oriented interface", + "homepage": "https://github.com/zendframework/zend-code", + "keywords": [ + "code", + "zf2" + ], + "time": "2016-06-30 22:35:27" + }, + { + "name": "zendframework/zend-diactoros", + "version": "1.3.5", + "source": { + "type": "git", + "url": "https://github.com/zendframework/zend-diactoros.git", + "reference": "b1d59735b672865dbeb930805029c24f226e3e77" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/zendframework/zend-diactoros/zipball/b1d59735b672865dbeb930805029c24f226e3e77", + "reference": "b1d59735b672865dbeb930805029c24f226e3e77", + "shasum": "" + }, + "require": { + "php": "^5.4 || ^7.0", + "psr/http-message": "~1.0" + }, + "provide": { + "psr/http-message-implementation": "~1.0.0" + }, + "require-dev": { + "phpunit/phpunit": "~4.6", + "squizlabs/php_codesniffer": "^2.3.1" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.3-dev", + "dev-develop": "1.4-dev" + } + }, + "autoload": { + "psr-4": { + "Zend\\Diactoros\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-2-Clause" + ], + "description": "PSR HTTP Message implementations", + "homepage": "https://github.com/zendframework/zend-diactoros", + "keywords": [ + "http", + "psr", + "psr-7" + ], + "time": "2016-03-17 18:02:05" + }, + { + "name": "zendframework/zend-escaper", + "version": "2.5.2", + "source": { + "type": "git", + "url": "https://github.com/zendframework/zend-escaper.git", + "reference": "2dcd14b61a72d8b8e27d579c6344e12c26141d4e" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/zendframework/zend-escaper/zipball/2dcd14b61a72d8b8e27d579c6344e12c26141d4e", + "reference": "2dcd14b61a72d8b8e27d579c6344e12c26141d4e", + "shasum": "" + }, + "require": { + "php": ">=5.5" + }, + "require-dev": { + "fabpot/php-cs-fixer": "1.7.*", + "phpunit/phpunit": "~4.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.5-dev", + "dev-develop": "2.6-dev" + } + }, + "autoload": { + "psr-4": { + "Zend\\Escaper\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "homepage": "https://github.com/zendframework/zend-escaper", + "keywords": [ + "escaper", + "zf2" + ], + "time": "2016-06-30 19:48:38" + }, + { + "name": "zendframework/zend-eventmanager", + "version": "3.0.1", + "source": { + "type": "git", + "url": "https://github.com/zendframework/zend-eventmanager.git", + "reference": "5c80bdee0e952be112dcec0968bad770082c3a6e" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/zendframework/zend-eventmanager/zipball/5c80bdee0e952be112dcec0968bad770082c3a6e", + "reference": "5c80bdee0e952be112dcec0968bad770082c3a6e", + "shasum": "" + }, + "require": { + "php": "^5.5 || ^7.0" + }, + "require-dev": { + "athletic/athletic": "^0.1", + "container-interop/container-interop": "^1.1.0", + "phpunit/phpunit": "~4.0", + "squizlabs/php_codesniffer": "^2.0", + "zendframework/zend-stdlib": "^2.7.3 || ^3.0" + }, + "suggest": { + "container-interop/container-interop": "^1.1.0, to use the lazy listeners feature", + "zendframework/zend-stdlib": "^2.7.3 || ^3.0, to use the FilterChain feature" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.0-dev", + "dev-develop": "3.1-dev" + } + }, + "autoload": { + "psr-4": { + "Zend\\EventManager\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "description": "Trigger and listen to events within a PHP application", + "homepage": "https://github.com/zendframework/zend-eventmanager", + "keywords": [ + "event", + "eventmanager", + "events", + "zf2" + ], + "time": "2016-02-18 20:53:00" + }, + { + "name": "zendframework/zend-expressive", + "version": "1.0.0", + "source": { + "type": "git", + "url": "https://github.com/zendframework/zend-expressive.git", + "reference": "4e6b1821e116425c76a515cae9b78141f17b2e1a" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/zendframework/zend-expressive/zipball/4e6b1821e116425c76a515cae9b78141f17b2e1a", + "reference": "4e6b1821e116425c76a515cae9b78141f17b2e1a", + "shasum": "" + }, + "require": { + "container-interop/container-interop": "^1.1", + "php": "^5.5 || ^7.0", + "psr/http-message": "^1.0", + "zendframework/zend-diactoros": "^1.1", + "zendframework/zend-expressive-router": "^1.1", + "zendframework/zend-expressive-template": "^1.0.1", + "zendframework/zend-stratigility": "^1.1" + }, + "require-dev": { + "filp/whoops": "^1.1", + "phpunit/phpunit": "^4.7", + "squizlabs/php_codesniffer": "^2.3", + "zendframework/zend-expressive-aurarouter": "^1.0", + "zendframework/zend-expressive-fastroute": "^1.0", + "zendframework/zend-expressive-zendrouter": "^1.0", + "zendframework/zend-servicemanager": "^2.6" + }, + "suggest": { + "aura/di": "3.0.*@beta to make use of Aura.Di dependency injection container", + "filp/whoops": "^1.1 to use the Whoops error handler", + "xtreamwayz/pimple-container-interop": "^1.0 to use Pimple for dependency injection", + "zendframework/zend-expressive-aurarouter": "^1.0 to use the Aura.Router routing adapter", + "zendframework/zend-expressive-fastroute": "^1.0 to use the FastRoute routing adapter", + "zendframework/zend-expressive-helpers": "^1.0 for its UrlHelper, ServerUrlHelper, and BodyParseMiddleware", + "zendframework/zend-expressive-platesrenderer": "^1.0 to use the Plates template renderer", + "zendframework/zend-expressive-twigrenderer": "^1.0 to use the Twig template renderer", + "zendframework/zend-expressive-zendrouter": "^1.0 to use the zend-mvc routing adapter", + "zendframework/zend-expressive-zendviewrenderer": "^1.0 to use the zend-view PhpRenderer template renderer", + "zendframework/zend-servicemanager": "^2.5 to use zend-servicemanager for dependency injection" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0-dev", + "dev-develop": "1.1-dev" + } + }, + "autoload": { + "psr-4": { + "Zend\\Expressive\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "description": "PSR-7 Middleware Microframework based on Stratigility", + "keywords": [ + "http", + "middleware", + "psr", + "psr-7" + ], + "time": "2016-01-28 15:49:52" + }, + { + "name": "zendframework/zend-expressive-fastroute", + "version": "1.2.0", + "source": { + "type": "git", + "url": "https://github.com/zendframework/zend-expressive-fastroute.git", + "reference": "2d08527ee8b4ac8709a9dae626f868eaaa1d84e6" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/zendframework/zend-expressive-fastroute/zipball/2d08527ee8b4ac8709a9dae626f868eaaa1d84e6", + "reference": "2d08527ee8b4ac8709a9dae626f868eaaa1d84e6", + "shasum": "" + }, + "require": { + "nikic/fast-route": "^1.0.0", + "php": "^5.5 || ^7.0", + "psr/http-message": "^1.0", + "zendframework/zend-expressive-router": "^1.0" + }, + "require-dev": { + "phpunit/phpunit": "^4.7", + "squizlabs/php_codesniffer": "^2.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.1-dev", + "dev-develop": "1.2-dev" + } + }, + "autoload": { + "psr-4": { + "Zend\\Expressive\\Router\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "description": "FastRoute integration for Expressive", + "keywords": [ + "FastRoute", + "expressive", + "http", + "middleware", + "psr", + "psr-7" + ], + "time": "2016-06-16 13:37:19" + }, + { + "name": "zendframework/zend-expressive-helpers", + "version": "2.0.0", + "source": { + "type": "git", + "url": "https://github.com/zendframework/zend-expressive-helpers.git", + "reference": "7d7cf9573638448acdde5b2ee4a30ebd33401fb7" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/zendframework/zend-expressive-helpers/zipball/7d7cf9573638448acdde5b2ee4a30ebd33401fb7", + "reference": "7d7cf9573638448acdde5b2ee4a30ebd33401fb7", + "shasum": "" + }, + "require": { + "container-interop/container-interop": "^1.1", + "php": "^5.5 || ^7.0", + "psr/http-message": "^1.0", + "zendframework/zend-expressive-router": "^1.1" + }, + "require-dev": { + "phpunit/phpunit": "^4.7", + "squizlabs/php_codesniffer": "^2.3", + "zendframework/zend-diactoros": "^1.2" + }, + "suggest": { + "aura/di": "3.0.*@beta to make use of Aura.Di dependency injection container", + "mouf/pimple-interop": "^1.0 to use Pimple for dependency injection", + "zendframework/zend-servicemanager": "^2.5 to use zend-servicemanager for dependency injection" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.0-dev", + "dev-develop": "2.1-dev" + } + }, + "autoload": { + "psr-4": { + "Zend\\Expressive\\Helper\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "description": "Helper/Utility classes for Expressive", + "keywords": [ + "expressive", + "http", + "middleware", + "psr", + "psr-7" + ], + "time": "2016-01-18 19:53:28" + }, + { + "name": "zendframework/zend-expressive-router", + "version": "1.2.0", + "source": { + "type": "git", + "url": "https://github.com/zendframework/zend-expressive-router.git", + "reference": "ec11c758e067c3eef579cb51dcabfcbf5de2ec03" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/zendframework/zend-expressive-router/zipball/ec11c758e067c3eef579cb51dcabfcbf5de2ec03", + "reference": "ec11c758e067c3eef579cb51dcabfcbf5de2ec03", + "shasum": "" + }, + "require": { + "php": "^5.5 || ^7.0", + "psr/http-message": "^1.0" + }, + "require-dev": { + "phpunit/phpunit": "^4.7", + "squizlabs/php_codesniffer": "^2.3" + }, + "suggest": { + "zendframework/zend-expressive-aurarouter": "^0.1 to use the Aura.Router routing adapter", + "zendframework/zend-expressive-fastroute": "^0.1 to use the FastRoute routing adapter", + "zendframework/zend-expressive-zendrouter": "^0.1 to use the zend-mvc routing adapter" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.2-dev", + "dev-develop": "1.3-dev" + } + }, + "autoload": { + "psr-4": { + "Zend\\Expressive\\Router\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "description": "Router subcomponent for Expressive", + "keywords": [ + "expressive", + "http", + "middleware", + "psr", + "psr-7" + ], + "time": "2016-01-18 20:10:33" + }, + { + "name": "zendframework/zend-expressive-template", + "version": "1.0.3", + "source": { + "type": "git", + "url": "https://github.com/zendframework/zend-expressive-template.git", + "reference": "2aac4050ebcf9a2c883dc23cf74671da02a66a7b" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/zendframework/zend-expressive-template/zipball/2aac4050ebcf9a2c883dc23cf74671da02a66a7b", + "reference": "2aac4050ebcf9a2c883dc23cf74671da02a66a7b", + "shasum": "" + }, + "require": { + "php": ">=5.5" + }, + "require-dev": { + "phpunit/phpunit": "^4.7", + "squizlabs/php_codesniffer": "^2.3" + }, + "suggest": { + "zendframework/zend-expressive-platesrenderer": "^0.1 to use the Plates template renderer", + "zendframework/zend-expressive-twigrenderer": "^0.1 to use the Twig template renderer", + "zendframework/zend-expressive-zendviewrenderer": "^0.1 to use the zend-view PhpRenderer template renderer" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0-dev", + "dev-develop": "1.1-dev" + } + }, + "autoload": { + "psr-4": { + "Zend\\Expressive\\Template\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "description": "Template subcomponent for Expressive", + "keywords": [ + "expressive", + "template" + ], + "time": "2016-01-28 15:44:23" + }, + { + "name": "zendframework/zend-filter", + "version": "2.7.1", + "source": { + "type": "git", + "url": "https://github.com/zendframework/zend-filter.git", + "reference": "84c50246428efb0a1e52868e162dab3e149d5b80" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/zendframework/zend-filter/zipball/84c50246428efb0a1e52868e162dab3e149d5b80", + "reference": "84c50246428efb0a1e52868e162dab3e149d5b80", + "shasum": "" + }, + "require": { + "php": "^5.5 || ^7.0", + "zendframework/zend-stdlib": "^2.7 || ^3.0" + }, + "require-dev": { + "fabpot/php-cs-fixer": "1.7.*", + "pear/archive_tar": "^1.4", + "phpunit/phpunit": "~4.0", + "zendframework/zend-crypt": "^2.6", + "zendframework/zend-servicemanager": "^2.7.5 || ^3.0.3", + "zendframework/zend-uri": "^2.5" + }, + "suggest": { + "zendframework/zend-crypt": "Zend\\Crypt component, for encryption filters", + "zendframework/zend-i18n": "Zend\\I18n component for filters depending on i18n functionality", + "zendframework/zend-servicemanager": "Zend\\ServiceManager component, for using the filter chain functionality", + "zendframework/zend-uri": "Zend\\Uri component, for the UriNormalize filter" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.7-dev", + "dev-develop": "2.8-dev" + }, + "zf": { + "component": "Zend\\Filter", + "config-provider": "Zend\\Filter\\ConfigProvider" + } + }, + "autoload": { + "psr-4": { + "Zend\\Filter\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "description": "provides a set of commonly needed data filters", + "homepage": "https://github.com/zendframework/zend-filter", + "keywords": [ + "filter", + "zf2" + ], + "time": "2016-04-18 18:32:43" + }, + { + "name": "zendframework/zend-hydrator", + "version": "2.2.1", + "source": { + "type": "git", + "url": "https://github.com/zendframework/zend-hydrator.git", + "reference": "0ac0d3e569781f1895670b0c8d0dc7f25b8a3182" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/zendframework/zend-hydrator/zipball/0ac0d3e569781f1895670b0c8d0dc7f25b8a3182", + "reference": "0ac0d3e569781f1895670b0c8d0dc7f25b8a3182", + "shasum": "" + }, + "require": { + "php": "^5.5 || ^7.0", + "zendframework/zend-stdlib": "^3.0" + }, + "require-dev": { + "phpunit/phpunit": "^4.5", + "squizlabs/php_codesniffer": "^2.3.1", + "zendframework/zend-eventmanager": "^3.0", + "zendframework/zend-filter": "^2.6", + "zendframework/zend-inputfilter": "^2.6", + "zendframework/zend-serializer": "^2.6.1", + "zendframework/zend-servicemanager": "^2.7.5 || ^3.0.3" + }, + "suggest": { + "zendframework/zend-eventmanager": "^2.6.2 || ^3.0, to support aggregate hydrator usage", + "zendframework/zend-filter": "^2.6, to support naming strategy hydrator usage", + "zendframework/zend-serializer": "^2.6.1, to use the SerializableStrategy", + "zendframework/zend-servicemanager": "^2.7.5 || ^3.0.3, to support hydrator plugin manager usage" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-release-1.0": "1.0-dev", + "dev-release-1.1": "1.1-dev", + "dev-master": "2.2-dev", + "dev-develop": "2.3-dev" + }, + "zf": { + "component": "Zend\\Hydrator", + "config-provider": "Zend\\Hydrator\\ConfigProvider" + } + }, + "autoload": { + "psr-4": { + "Zend\\Hydrator\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "homepage": "https://github.com/zendframework/zend-hydrator", + "keywords": [ + "hydrator", + "zf2" + ], + "time": "2016-04-18 17:59:29" + }, + { + "name": "zendframework/zend-json", + "version": "3.0.0", + "source": { + "type": "git", + "url": "https://github.com/zendframework/zend-json.git", + "reference": "f42a1588e75c2a3e338cd94c37906231e616daab" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/zendframework/zend-json/zipball/f42a1588e75c2a3e338cd94c37906231e616daab", + "reference": "f42a1588e75c2a3e338cd94c37906231e616daab", + "shasum": "" + }, + "require": { + "php": "^5.5 || ^7.0" + }, + "require-dev": { + "phpunit/phpunit": "~4.0", + "squizlabs/php_codesniffer": "^2.3", + "zendframework/zend-stdlib": "^2.7 || ^3.0" + }, + "suggest": { + "zendframework/zend-json-server": "For implementing JSON-RPC servers", + "zendframework/zend-xml2json": "For converting XML documents to JSON" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.0-dev", + "dev-develop": "3.1-dev" + } + }, + "autoload": { + "psr-4": { + "Zend\\Json\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "description": "provides convenience methods for serializing native PHP to JSON and decoding JSON to native PHP", + "homepage": "https://github.com/zendframework/zend-json", + "keywords": [ + "json", + "zf2" + ], + "time": "2016-04-01 02:34:00" + }, + { + "name": "zendframework/zend-servicemanager", + "version": "3.1.1", + "source": { + "type": "git", + "url": "https://github.com/zendframework/zend-servicemanager.git", + "reference": "f701b0d322741b0c8d8ca1288f249a49438029cd" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/zendframework/zend-servicemanager/zipball/f701b0d322741b0c8d8ca1288f249a49438029cd", + "reference": "f701b0d322741b0c8d8ca1288f249a49438029cd", + "shasum": "" + }, + "require": { + "container-interop/container-interop": "~1.0", + "php": "^5.5 || ^7.0" + }, + "provide": { + "container-interop/container-interop-implementation": "^1.1" + }, + "require-dev": { + "ocramius/proxy-manager": "^1.0 || ^2.0", + "phpbench/phpbench": "^0.10.0", + "phpunit/phpunit": "^4.6 || ^5.2.10", + "squizlabs/php_codesniffer": "^2.5.1" + }, + "suggest": { + "ocramius/proxy-manager": "ProxyManager 1.* to handle lazy initialization of services", + "zendframework/zend-stdlib": "zend-stdlib ^2.5 if you wish to use the MergeReplaceKey or MergeRemoveKey features in Config instances" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.1-dev", + "dev-develop": "3.2-dev" + } + }, + "autoload": { + "psr-4": { + "Zend\\ServiceManager\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "homepage": "https://github.com/zendframework/zend-servicemanager", + "keywords": [ + "service-manager", + "servicemanager", + "zf" + ], + "time": "2016-07-15 14:59:51" + }, + { + "name": "zendframework/zend-stdlib", + "version": "3.0.1", + "source": { + "type": "git", + "url": "https://github.com/zendframework/zend-stdlib.git", + "reference": "8bafa58574204bdff03c275d1d618aaa601588ae" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/zendframework/zend-stdlib/zipball/8bafa58574204bdff03c275d1d618aaa601588ae", + "reference": "8bafa58574204bdff03c275d1d618aaa601588ae", + "shasum": "" + }, + "require": { + "php": "^5.5 || ^7.0" + }, + "require-dev": { + "athletic/athletic": "~0.1", + "fabpot/php-cs-fixer": "1.7.*", + "phpunit/phpunit": "~4.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.0-dev", + "dev-develop": "3.1-dev" + } + }, + "autoload": { + "psr-4": { + "Zend\\Stdlib\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "homepage": "https://github.com/zendframework/zend-stdlib", + "keywords": [ + "stdlib", + "zf2" + ], + "time": "2016-04-12 21:19:36" + }, + { + "name": "zendframework/zend-stratigility", + "version": "1.2.1", + "source": { + "type": "git", + "url": "https://github.com/zendframework/zend-stratigility.git", + "reference": "b78388f096f669f9a9f15dabe5fa73c4d9fd9a09" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/zendframework/zend-stratigility/zipball/b78388f096f669f9a9f15dabe5fa73c4d9fd9a09", + "reference": "b78388f096f669f9a9f15dabe5fa73c4d9fd9a09", + "shasum": "" + }, + "require": { + "php": "^5.4.8 || ^7.0", + "psr/http-message": "~1.0.0", + "zendframework/zend-escaper": "~2.3" + }, + "require-dev": { + "phpunit/phpunit": "~4.7", + "squizlabs/php_codesniffer": "^2.3.1", + "zendframework/zend-diactoros": "~1.0" + }, + "suggest": { + "psr/http-message-implementation": "Please install a psr/http-message-implementation to consume Stratigility; e.g., zendframework/zend-diactoros" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.2-dev", + "dev-develop": "1.3-dev" + } + }, + "autoload": { + "psr-4": { + "Zend\\Stratigility\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "description": "Middleware for PHP", + "homepage": "https://github.com/zendframework/zend-stratigility", + "keywords": [ + "http", + "middleware", + "psr-7" + ], + "time": "2016-03-24 22:10:30" + } + ], + "packages-dev": [ + { + "name": "filp/whoops", + "version": "2.1.3", + "source": { + "type": "git", + "url": "https://github.com/filp/whoops.git", + "reference": "8828aaa2178e0a19325522e2a45282ff0a14649b" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/filp/whoops/zipball/8828aaa2178e0a19325522e2a45282ff0a14649b", + "reference": "8828aaa2178e0a19325522e2a45282ff0a14649b", + "shasum": "" + }, + "require": { + "php": ">=5.5.9" + }, + "require-dev": { + "mockery/mockery": "0.9.*", + "phpunit/phpunit": "^4.8 || ^5.0", + "symfony/var-dumper": "~3.0" + }, + "suggest": { + "symfony/var-dumper": "Pretty print complex values better with var-dumper available", + "whoops/soap": "Formats errors as SOAP responses" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.0-dev" + } + }, + "autoload": { + "psr-4": { + "Whoops\\": "src/Whoops/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Filipe Dobreira", + "homepage": "https://github.com/filp", + "role": "Developer" + } + ], + "description": "php error handling for cool kids", + "homepage": "https://github.com/filp/whoops", + "keywords": [ + "error", + "exception", + "handling", + "library", + "whoops", + "zf2" + ], + "time": "2016-05-06 18:25:35" + }, + { + "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.0", + "source": { + "type": "git", + "url": "https://github.com/phpDocumentor/ReflectionDocBlock.git", + "reference": "9270140b940ff02e58ec577c237274e92cd40cdd" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/9270140b940ff02e58ec577c237274e92cd40cdd", + "reference": "9270140b940ff02e58ec577c237274e92cd40cdd", + "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-06-10 09:48:41" + }, + { + "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": "2.2.4", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/php-code-coverage.git", + "reference": "eabf68b476ac7d0f73793aada060f1c1a9bf8979" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/eabf68b476ac7d0f73793aada060f1c1a9bf8979", + "reference": "eabf68b476ac7d0f73793aada060f1c1a9bf8979", + "shasum": "" + }, + "require": { + "php": ">=5.3.3", + "phpunit/php-file-iterator": "~1.3", + "phpunit/php-text-template": "~1.2", + "phpunit/php-token-stream": "~1.3", + "sebastian/environment": "^1.3.2", + "sebastian/version": "~1.0" + }, + "require-dev": { + "ext-xdebug": ">=2.1.4", + "phpunit/phpunit": "~4" + }, + "suggest": { + "ext-dom": "*", + "ext-xdebug": ">=2.2.1", + "ext-xmlwriter": "*" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.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": "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": "2015-10-06 15:47:00" + }, + { + "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": "4.8.27", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/phpunit.git", + "reference": "c062dddcb68e44b563f66ee319ddae2b5a322a90" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/c062dddcb68e44b563f66ee319ddae2b5a322a90", + "reference": "c062dddcb68e44b563f66ee319ddae2b5a322a90", + "shasum": "" + }, + "require": { + "ext-dom": "*", + "ext-json": "*", + "ext-pcre": "*", + "ext-reflection": "*", + "ext-spl": "*", + "php": ">=5.3.3", + "phpspec/prophecy": "^1.3.1", + "phpunit/php-code-coverage": "~2.1", + "phpunit/php-file-iterator": "~1.4", + "phpunit/php-text-template": "~1.2", + "phpunit/php-timer": "^1.0.6", + "phpunit/phpunit-mock-objects": "~2.3", + "sebastian/comparator": "~1.1", + "sebastian/diff": "~1.2", + "sebastian/environment": "~1.3", + "sebastian/exporter": "~1.2", + "sebastian/global-state": "~1.0", + "sebastian/version": "~1.0", + "symfony/yaml": "~2.1|~3.0" + }, + "suggest": { + "phpunit/php-invoker": "~1.1" + }, + "bin": [ + "phpunit" + ], + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "4.8.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-07-21 06:48:14" + }, + { + "name": "phpunit/phpunit-mock-objects", + "version": "2.3.8", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/phpunit-mock-objects.git", + "reference": "ac8e7a3db35738d56ee9a76e78a4e03d97628983" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit-mock-objects/zipball/ac8e7a3db35738d56ee9a76e78a4e03d97628983", + "reference": "ac8e7a3db35738d56ee9a76e78a4e03d97628983", + "shasum": "" + }, + "require": { + "doctrine/instantiator": "^1.0.2", + "php": ">=5.3.3", + "phpunit/php-text-template": "~1.2", + "sebastian/exporter": "~1.2" + }, + "require-dev": { + "phpunit/phpunit": "~4.4" + }, + "suggest": { + "ext-soap": "*" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.3.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": "2015-10-02 06:51:40" + }, + { + "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.7", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/environment.git", + "reference": "4e8f0da10ac5802913afc151413bc8c53b6c2716" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/4e8f0da10ac5802913afc151413bc8c53b6c2716", + "reference": "4e8f0da10ac5802913afc151413bc8c53b6c2716", + "shasum": "" + }, + "require": { + "php": ">=5.3.3" + }, + "require-dev": { + "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": "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-05-17 03:18:57" + }, + { + "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/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/version", + "version": "1.0.6", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/version.git", + "reference": "58b3a85e7999757d6ad81c787a1fbf5ff6c628c6" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/version/zipball/58b3a85e7999757d6ad81c787a1fbf5ff6c628c6", + "reference": "58b3a85e7999757d6ad81c787a1fbf5ff6c628c6", + "shasum": "" + }, + "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": "Library that helps with managing the version number of Git-hosted PHP projects", + "homepage": "https://github.com/sebastianbergmann/version", + "time": "2015-06-21 13:59:46" + }, + { + "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.3", + "source": { + "type": "git", + "url": "https://github.com/symfony/yaml.git", + "reference": "1819adf2066880c7967df7180f4f662b6f0567ac" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/yaml/zipball/1819adf2066880c7967df7180f4f662b6f0567ac", + "reference": "1819adf2066880c7967df7180f4f662b6f0567ac", + "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-07-17 14:02:08" + }, + { + "name": "webmozart/assert", + "version": "1.0.2", + "source": { + "type": "git", + "url": "https://github.com/webmozart/assert.git", + "reference": "30eed06dd6bc88410a4ff7f77b6d22f3ce13dbde" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/webmozart/assert/zipball/30eed06dd6bc88410a4ff7f77b6d22f3ce13dbde", + "reference": "30eed06dd6bc88410a4ff7f77b6d22f3ce13dbde", + "shasum": "" + }, + "require": { + "php": ">=5.3.3" + }, + "require-dev": { + "phpunit/phpunit": "^4.6" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0-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": "2015-08-24 13:29:44" + } + ], + "aliases": [], + "minimum-stability": "stable", + "stability-flags": { + "roave/security-advisories": 20 + }, + "prefer-stable": false, + "prefer-lowest": false, + "platform": { + "php": "^5.5 || ^7.0" + }, + "platform-dev": [] +} diff --git a/config/autoload/.gitignore b/config/autoload/.gitignore new file mode 100644 index 0000000..1a83fda --- /dev/null +++ b/config/autoload/.gitignore @@ -0,0 +1,2 @@ +local.php +*.local.php diff --git a/config/autoload/dependencies.global.php b/config/autoload/dependencies.global.php new file mode 100644 index 0000000..f6f05f9 --- /dev/null +++ b/config/autoload/dependencies.global.php @@ -0,0 +1,26 @@ + [ + // Use 'invokables' for constructor-less services, or services that do + // not require arguments to the constructor. Map a service name to the + // class name. + 'invokables' => [ + // Fully\Qualified\InterfaceName::class => Fully\Qualified\ClassName::class, + Helper\ServerUrlHelper::class => Helper\ServerUrlHelper::class, + ], + // Use 'factories' for services provided by callbacks/factory classes. + 'factories' => [ + Application::class => ApplicationFactory::class, + Helper\UrlHelper::class => Helper\UrlHelperFactory::class, + 'doctrine.entity_manager.orm_default' => \ContainerInteropDoctrine\EntityManagerFactory::class, + 'doctrine.hydrator' => \App\Hydrator\DoctrineObjectFactory::class, + ], + ], +]; diff --git a/config/autoload/doctrine.global.php b/config/autoload/doctrine.global.php new file mode 100644 index 0000000..e6fa6c3 --- /dev/null +++ b/config/autoload/doctrine.global.php @@ -0,0 +1,19 @@ + [ + 'driver' => [ + 'orm_default' => [ + 'class' => \Doctrine\Common\Persistence\Mapping\Driver\MappingDriverChain::class, + 'drivers' => [ + 'App\Entity' => 'my_entity', + ], + ], + 'my_entity' => [ + 'class' => \Doctrine\ORM\Mapping\Driver\AnnotationDriver::class, + 'cache' => 'array', + 'paths' => __DIR__ . '/../../src/App/Entity', + ], + ], + ], +]; diff --git a/config/autoload/doctrine.local.dist.php b/config/autoload/doctrine.local.dist.php new file mode 100644 index 0000000..6549fbe --- /dev/null +++ b/config/autoload/doctrine.local.dist.php @@ -0,0 +1,14 @@ + [ + 'connection' => [ + 'orm_default' => [ + 'params' => [ + 'url' => 'mysqli://user:passwd@host/database', + 'charset' => 'UTF8', + ], + ], + ], + ], +]; diff --git a/config/autoload/errorhandler.local.dist.php b/config/autoload/errorhandler.local.dist.php new file mode 100644 index 0000000..de70e4f --- /dev/null +++ b/config/autoload/errorhandler.local.dist.php @@ -0,0 +1,21 @@ + [ + 'invokables' => [ + 'Zend\Expressive\Whoops' => Whoops\Run::class, + 'Zend\Expressive\WhoopsPageHandler' => Whoops\Handler\PrettyPageHandler::class, + ], + 'factories' => [ + 'Zend\Expressive\FinalHandler' => Zend\Expressive\Container\WhoopsErrorHandlerFactory::class, + ], + ], + + 'whoops' => [ + 'json_exceptions' => [ + 'display' => true, + 'show_trace' => true, + 'ajax_only' => true, + ], + ], +]; diff --git a/config/autoload/local.php.dist b/config/autoload/local.php.dist new file mode 100644 index 0000000..75c8b9c --- /dev/null +++ b/config/autoload/local.php.dist @@ -0,0 +1,7 @@ + true, + + 'config_cache_enabled' => false, +]; diff --git a/config/autoload/middleware-pipeline.global.php b/config/autoload/middleware-pipeline.global.php new file mode 100644 index 0000000..6766540 --- /dev/null +++ b/config/autoload/middleware-pipeline.global.php @@ -0,0 +1,69 @@ + [ + 'factories' => [ + Helper\ServerUrlMiddleware::class => Helper\ServerUrlMiddlewareFactory::class, + Helper\UrlHelperMiddleware::class => Helper\UrlHelperMiddlewareFactory::class, + ], + ], + // This can be used to seed pre- and/or post-routing middleware + 'middleware_pipeline' => [ + // An array of middleware to register. Each item is of the following + // specification: + // + // [ + // Required: + // 'middleware' => 'Name or array of names of middleware services and/or callables', + // Optional: + // 'path' => '/path/to/match', // string; literal path prefix to match + // // middleware will not execute + // // if path does not match! + // 'error' => true, // boolean; true for error middleware + // 'priority' => 1, // int; higher values == register early; + // // lower/negative == register last; + // // default is 1, if none is provided. + // ], + // + // While the ApplicationFactory ignores the keys associated with + // specifications, they can be used to allow merging related values + // defined in multiple configuration files/locations. This file defines + // some conventional keys for middleware to execute early, routing + // middleware, and error middleware. + 'always' => [ + 'middleware' => [ + // Add more middleware here that you want to execute on + // every request: + // - bootstrapping + // - pre-conditions + // - modifications to outgoing responses + Helper\ServerUrlMiddleware::class, + ], + 'priority' => 10000, + ], + + 'routing' => [ + 'middleware' => [ + ApplicationFactory::ROUTING_MIDDLEWARE, + Helper\UrlHelperMiddleware::class, + // Add more middleware here that needs to introspect the routing + // results; this might include: + // - route-based authentication + // - route-based validation + // - etc. + ApplicationFactory::DISPATCH_MIDDLEWARE, + ], + 'priority' => 1, + ], + + 'error' => [ + 'middleware' => [ + // Add error middleware here. + ], + 'error' => true, + 'priority' => -10000, + ], + ], +]; diff --git a/config/autoload/routes.global.php b/config/autoload/routes.global.php new file mode 100644 index 0000000..b8fc18d --- /dev/null +++ b/config/autoload/routes.global.php @@ -0,0 +1,62 @@ + [ + 'invokables' => [ + Zend\Expressive\Router\RouterInterface::class => Zend\Expressive\Router\FastRouteRouter::class, + App\Action\PingAction::class => App\Action\PingAction::class, + ], + 'factories' => [ + App\Action\HomePageAction::class => App\Action\HomePageFactory::class, + App\Action\Article\ListAction::class => App\Action\Article\ListFactory::class, + App\Action\Article\GetAction::class => App\Action\Article\GetFactory::class, + App\Action\Article\PostAction::class => App\Action\Article\PostFactory::class, + App\Action\Article\PutAction::class => App\Action\Article\PutFactory::class, + App\Action\Article\DeleteAction::class => App\Action\Article\DeleteFactory::class, + ], + ], + 'routes' => [ + [ + 'name' => 'home', + 'path' => '/', + 'middleware' => App\Action\HomePageAction::class, + 'allowed_methods' => ['GET'], + ], + [ + 'name' => 'api.article.list', + 'path' => '/api/article', + 'middleware' => App\Action\Article\ListAction::class, + 'allowed_methods' => ['GET'], + ], + [ + 'name' => 'api.article.get', + 'path' => '/api/article/{id:\d+}', + 'middleware' => App\Action\Article\GetAction::class, + 'allowed_methods' => ['GET'], + ], + [ + 'name' => 'api.article.add', + 'path' => '/api/article', + 'middleware' => App\Action\Article\PostAction::class, + 'allowed_methods' => ['POST'], + ], + [ + 'name' => 'api.article.update', + 'path' => '/api/article/{id:\d+}', + 'middleware' => App\Action\Article\PutAction::class, + 'allowed_methods' => ['PUT'], + ], + [ + 'name' => 'api.article.delete', + 'path' => '/api/article/{id:\d+}', + 'middleware' => App\Action\Article\DeleteAction::class, + 'allowed_methods' => ['DELETE'], + ], + [ + 'name' => 'api.ping', + 'path' => '/api/ping', + 'middleware' => App\Action\PingAction::class, + 'allowed_methods' => ['GET'], + ], + ], +]; diff --git a/config/autoload/zend-expressive.global.php b/config/autoload/zend-expressive.global.php new file mode 100644 index 0000000..44e980c --- /dev/null +++ b/config/autoload/zend-expressive.global.php @@ -0,0 +1,14 @@ + false, + + 'config_cache_enabled' => false, + + 'zend-expressive' => [ + 'error_handler' => [ + 'template_404' => 'error::404', + 'template_error' => 'error::error', + ], + ], +]; diff --git a/config/config.php b/config/config.php new file mode 100644 index 0000000..a5446be --- /dev/null +++ b/config/config.php @@ -0,0 +1,35 @@ +configureServiceManager($container); + +// Inject config +$container->setService('config', $config); + +return $container; diff --git a/data/.gitignore b/data/.gitignore new file mode 100644 index 0000000..d6b7ef3 --- /dev/null +++ b/data/.gitignore @@ -0,0 +1,2 @@ +* +!.gitignore diff --git a/nbproject/private/private.properties b/nbproject/private/private.properties new file mode 100644 index 0000000..dae3f69 --- /dev/null +++ b/nbproject/private/private.properties @@ -0,0 +1,9 @@ +auxiliary.org-netbeans-modules-php-editor.fluent_2e_setter_2e_project_2e_property=true +auxiliary.org-netbeans-modules-php-editor.getter_2e_setter_2e_method_2e_name_2e_generation=AS_JAVA +auxiliary.org-netbeans-modules-php-editor.public_2e_modifier_2e_project_2e_property=true +copy.src.files=false +copy.src.on.open=false +copy.src.target=/var/www/simen-backend-middleware +index.file= +run.as=LOCAL +url=http://localhost/simen-backend-middleware/ diff --git a/nbproject/project.properties b/nbproject/project.properties new file mode 100644 index 0000000..76f6f91 --- /dev/null +++ b/nbproject/project.properties @@ -0,0 +1,7 @@ +include.path=${php.global.include.path} +php.version=PHP_56 +source.encoding=UTF-8 +src.dir=. +tags.asp=false +tags.short=false +web.root=. diff --git a/nbproject/project.xml b/nbproject/project.xml new file mode 100644 index 0000000..5807ac1 --- /dev/null +++ b/nbproject/project.xml @@ -0,0 +1,9 @@ + + + org.netbeans.modules.php.project + + + simen-backend-middleware + + + diff --git a/phpcs.xml b/phpcs.xml new file mode 100644 index 0000000..f032dbb --- /dev/null +++ b/phpcs.xml @@ -0,0 +1,20 @@ + + + Zend Framework coding standard + + + + + + + + + + + + + + + + src + diff --git a/phpunit.xml.dist b/phpunit.xml.dist new file mode 100644 index 0000000..bb69885 --- /dev/null +++ b/phpunit.xml.dist @@ -0,0 +1,13 @@ + + + + ./test + + + + + + src + + + diff --git a/public/.htaccess b/public/.htaccess new file mode 100644 index 0000000..a5c4081 --- /dev/null +++ b/public/.htaccess @@ -0,0 +1,17 @@ +RewriteEngine On +# The following rule tells Apache that if the requested filename +# exists, simply serve it. +RewriteCond %{REQUEST_FILENAME} -s [OR] +RewriteCond %{REQUEST_FILENAME} -l [OR] +RewriteCond %{REQUEST_FILENAME} -d +RewriteRule ^.*$ - [NC,L] + +# The following rewrites all other queries to index.php. The +# condition ensures that if you are using Apache aliases to do +# mass virtual hosting, the base path will be prepended to +# allow proper resolution of the index.php file; it will work +# in non-aliased environments as well, providing a safe, one-size +# fits all solution. +RewriteCond %{REQUEST_URI}::$1 ^(/.+)(.+)::\2$ +RewriteRule ^(.*) - [E=BASE:%1] +RewriteRule ^(.*)$ %{ENV:BASE}index.php [NC,L] diff --git a/public/favicon.ico b/public/favicon.ico new file mode 100644 index 0000000..17f1199 Binary files /dev/null and b/public/favicon.ico differ diff --git a/public/index.php b/public/index.php new file mode 100644 index 0000000..f84c136 --- /dev/null +++ b/public/index.php @@ -0,0 +1,18 @@ +get(\Zend\Expressive\Application::class); +$app->run(); diff --git a/public/zf-logo.png b/public/zf-logo.png new file mode 100644 index 0000000..ea5880e Binary files /dev/null and b/public/zf-logo.png differ diff --git a/src/App/Action/AbstractFactory.php b/src/App/Action/AbstractFactory.php new file mode 100644 index 0000000..3593493 --- /dev/null +++ b/src/App/Action/AbstractFactory.php @@ -0,0 +1,27 @@ +get('doctrine.entity_manager.orm_default'); + } + + /** + * @param ContainerInterface $container + * @return \App\Hydrator\DoctrineObject + */ + protected function getDoctrineHydrator(ContainerInterface $container) + { + return $container->get('doctrine.hydrator'); + } +} \ No newline at end of file diff --git a/src/App/Action/AbstractFormAction.php b/src/App/Action/AbstractFormAction.php new file mode 100644 index 0000000..1b1cee5 --- /dev/null +++ b/src/App/Action/AbstractFormAction.php @@ -0,0 +1,74 @@ +getParsedBody(); + + if (!empty($body)) { + return $body; + } + + return $this->parseRequestData( + $request->getBody()->getContents(), + $request->getHeaderLine('content-type') + ); + } + + /** + * + * @param type $input + * @param type $contentType + * @return type + */ + public function parseRequestData($input, $contentType) + { + $contentTypeParts = preg_split('/\s*[;,]\s*/', $contentType); + $parser = $this->returnParserContentType($contentTypeParts[0]); + + return $parser($input); + } + + /** + * + * @param type $contentType + * @return type + */ + public function returnParserContentType($contentType) + { + if ($contentType === 'application/x-www-form-urlencoded') { + return function ($input) { + parse_str($input, $data); + return $data; + }; + } elseif ($contentType === 'application/json') { + return function ($input) { + $jsonDecoder = new \Zend\Json\Json(); + try { + return $jsonDecoder->decode($input, \Zend\Json\Json::TYPE_ARRAY); + } catch (Exception $e) { + return new ApiProblem(400, 'Data Parsing Error.'); + } + }; + } elseif ($contentType === 'multipart/form-data') { + return function ($input) { + return $input; + }; + } + + return function ($input) { + return $input; + }; + } +} \ No newline at end of file diff --git a/src/App/Action/Article/DeleteAction.php b/src/App/Action/Article/DeleteAction.php new file mode 100644 index 0000000..02064c0 --- /dev/null +++ b/src/App/Action/Article/DeleteAction.php @@ -0,0 +1,49 @@ +em = $em; + } + + public function __invoke(ServerRequestInterface $request, ResponseInterface $response, callable $next = null) + { + $id = $request->getAttribute('id'); + + if (null === ($entity = $this->em->find(Article::class, $id))) { + $ret = new JsonResponse([ + 'success' => false + ]); + return $ret->withStatus(404); + } + + try { + $this->em->remove($entity); + $this->em->flush(); + } catch (\Exception $ex) { + $ret = new JsonResponse([ + 'success' => false + ]); + return $ret->withStatus(500); + } + + return new JsonResponse([ + 'success' => true, + ]); + } +} \ No newline at end of file diff --git a/src/App/Action/Article/DeleteFactory.php b/src/App/Action/Article/DeleteFactory.php new file mode 100644 index 0000000..ec3e8ff --- /dev/null +++ b/src/App/Action/Article/DeleteFactory.php @@ -0,0 +1,17 @@ +getEntityManager($container); + return new DeleteAction($em); + } +} \ No newline at end of file diff --git a/src/App/Action/Article/GetAction.php b/src/App/Action/Article/GetAction.php new file mode 100644 index 0000000..ffd3ead --- /dev/null +++ b/src/App/Action/Article/GetAction.php @@ -0,0 +1,51 @@ +em = $em; + } + + public function __invoke(ServerRequestInterface $request, ResponseInterface $response, callable $next = null) + { + $id = $request->getAttribute('id'); + $qb = $this->em->createQueryBuilder(); + + $entity = $qb->select('a,u,c') + ->from(Article::class, 'a') + ->leftJoin('a.author', 'u') + ->leftJoin('a.comments', 'c') + ->where('a.id = :aid') + ->setParameter('aid', $id) + ->getQuery() + ->getOneOrNullResult(Query::HYDRATE_ARRAY); + + if (null === $entity) { + $ret = new JsonResponse([ + 'success' => false + ]); + return $ret->withStatus(404); + } + + return new JsonResponse([ + 'success' => true, + 'result' => $entity, + ]); + } +} \ No newline at end of file diff --git a/src/App/Action/Article/GetFactory.php b/src/App/Action/Article/GetFactory.php new file mode 100644 index 0000000..7829b9b --- /dev/null +++ b/src/App/Action/Article/GetFactory.php @@ -0,0 +1,17 @@ +getEntityManager($container); + return new GetAction($em); + } +} \ No newline at end of file diff --git a/src/App/Action/Article/ListAction.php b/src/App/Action/Article/ListAction.php new file mode 100644 index 0000000..0f2f503 --- /dev/null +++ b/src/App/Action/Article/ListAction.php @@ -0,0 +1,39 @@ +em = $em; + } + + public function __invoke(ServerRequestInterface $request, ResponseInterface $response, callable $next = null) + { + $qb = $this->em->createQueryBuilder(); + $entities = $qb->select('a,u,c') + ->from(Article::class, 'a') + ->leftJoin('a.author', 'u') + ->leftJoin('a.comments', 'c') + ->getQuery() + ->getArrayResult(); + + return new JsonResponse([ + 'success' => true, + 'result' => $entities, + ]); + } +} \ No newline at end of file diff --git a/src/App/Action/Article/ListFactory.php b/src/App/Action/Article/ListFactory.php new file mode 100644 index 0000000..ac44ab6 --- /dev/null +++ b/src/App/Action/Article/ListFactory.php @@ -0,0 +1,17 @@ +getEntityManager($container); + return new ListAction($em); + } +} \ No newline at end of file diff --git a/src/App/Action/Article/PostAction.php b/src/App/Action/Article/PostAction.php new file mode 100644 index 0000000..26447ee --- /dev/null +++ b/src/App/Action/Article/PostAction.php @@ -0,0 +1,45 @@ +em = $em; + $this->hydrator = $hydrator; + } + + public function __invoke(ServerRequestInterface $request, ResponseInterface $response, callable $next = null) + { + $data = $this->getRequestData($request); + + $entity = $this->hydrator->hydrate($data, new Article()); + $this->em->persist($entity); + $this->em->flush(); + + return new JsonResponse([ + 'success' => true, + 'result' => $entity, + ]); + } +} \ No newline at end of file diff --git a/src/App/Action/Article/PostFactory.php b/src/App/Action/Article/PostFactory.php new file mode 100644 index 0000000..e28e1e2 --- /dev/null +++ b/src/App/Action/Article/PostFactory.php @@ -0,0 +1,18 @@ +getEntityManager($container); + $hydrator = $this->getDoctrineHydrator($container); + return new PostAction($em, $hydrator); + } +} \ No newline at end of file diff --git a/src/App/Action/Article/PutAction.php b/src/App/Action/Article/PutAction.php new file mode 100644 index 0000000..3ab0edc --- /dev/null +++ b/src/App/Action/Article/PutAction.php @@ -0,0 +1,53 @@ +em = $em; + $this->hydrator = $hydrator; + } + + public function __invoke(ServerRequestInterface $request, ResponseInterface $response, callable $next = null) + { + $id = $request->getAttribute('id', false); + + if (null === ($entity = $this->em->find(Article::class, $id))) { + $ret = new JsonResponse([ + 'success' => false + ]); + return $ret->withStatus(404); + } + + $data = $this->getRequestData($request); + $entity = $this->hydrator->hydrate($data, $entity); + $this->em->persist($entity); + $this->em->flush(); + + return new JsonResponse([ + 'success' => true, + 'result' => $entity, + ]); + } +} \ No newline at end of file diff --git a/src/App/Action/Article/PutFactory.php b/src/App/Action/Article/PutFactory.php new file mode 100644 index 0000000..77e43eb --- /dev/null +++ b/src/App/Action/Article/PutFactory.php @@ -0,0 +1,18 @@ +getEntityManager($container); + $hydrator = $this->getDoctrineHydrator($container); + return new PutAction($em, $hydrator); + } +} \ No newline at end of file diff --git a/src/App/Action/HomePageAction.php b/src/App/Action/HomePageAction.php new file mode 100644 index 0000000..617b880 --- /dev/null +++ b/src/App/Action/HomePageAction.php @@ -0,0 +1,43 @@ +em = $em; + } + + public function __invoke(ServerRequestInterface $request, ResponseInterface $response, callable $next = null) + { + $qb = $this->em->createQueryBuilder(); + $user = $qb->select('u, a, ac, uc') + ->from(User::class, 'u') + ->leftJoin('u.comments', 'uc') + ->leftJoin('u.articles', 'a') + ->leftJoin('a.comments', 'ac') + ->where('u.id = :uid') + ->setParameter('uid', 1) + ->getQuery() + ->getSingleResult(Query::HYDRATE_ARRAY); + + return new JsonResponse([ + 'welcome' => 'Congratulations! You have reached our API endpoint.', + 'user' => $user, + ]); + } +} \ No newline at end of file diff --git a/src/App/Action/HomePageFactory.php b/src/App/Action/HomePageFactory.php new file mode 100644 index 0000000..5689647 --- /dev/null +++ b/src/App/Action/HomePageFactory.php @@ -0,0 +1,16 @@ +get('doctrine.entity_manager.orm_default'); + return new HomePageAction($em); + } +} \ No newline at end of file diff --git a/src/App/Action/PingAction.php b/src/App/Action/PingAction.php new file mode 100644 index 0000000..ea2ae22 --- /dev/null +++ b/src/App/Action/PingAction.php @@ -0,0 +1,15 @@ + time()]); + } +} diff --git a/src/App/Entity/Article.php b/src/App/Entity/Article.php new file mode 100644 index 0000000..105afa3 --- /dev/null +++ b/src/App/Entity/Article.php @@ -0,0 +1,180 @@ +comments = new ArrayCollection(); + } + + /** + * @return int + */ + public function getId() + { + return $this->id; + } + + /** + * @return string + */ + public function getTitle() + { + return $this->title; + } + + /** + * @return string + */ + public function getContent() + { + return $this->content; + } + + /** + * @return User + */ + public function getAuthor() + { + return $this->author; + } + + /** + * @return Comment[] + */ + public function getComments() + { + return $this->comments; + } + + /** + * @return bool + */ + public function getVisible() + { + return $this->visible; + } + + /** + * @param int $id + * @return Article + */ + public function setId(int $id) + { + $this->id = $id; + return $this; + } + + /** + * @param string $title + * @return Article + */ + public function setTitle(string $title) + { + $this->title = $title; + return $this; + } + + /** + * @param string $content + * @return Article + */ + public function setContent(string $content) + { + $this->content = $content; + return $this; + } + + /** + * @param User $author + * @return Article + */ + public function setAuthor(User $author) + { + $this->author = $author; + return $this; + } + + /** + * @param Comment[] $comments + * @return Article + */ + public function setComments(array $comments) + { + $this->comments = $comments; + return $this; + } + + /** + * @param bool $visible + * @return Article + */ + public function setVisible(bool $visible) + { + $this->visible = $visible; + return $this; + } + + public function jsonSerialize() + { + return [ + 'id' => $this->id, + 'title' => $this->title, + 'content' => $this->content, + 'author' => $this->author, + 'comments' => $this->comments, + 'visible' => $this->visible, + ]; + } +} \ No newline at end of file diff --git a/src/App/Entity/Comment.php b/src/App/Entity/Comment.php new file mode 100644 index 0000000..a7f2560 --- /dev/null +++ b/src/App/Entity/Comment.php @@ -0,0 +1,178 @@ +id; + } + + /** + * @return string + */ + public function getContent() + { + return $this->content; + } + + /** + * @return DateTime + */ + public function getCreatedAt() + { + return $this->createdAt; + } + + /** + * @return Article + */ + public function getArticle() + { + return $this->article; + } + + /** + * @return User + */ + public function getAuthor() + { + return $this->author; + } + + /** + * @return bool + */ + public function getVisible() + { + return $this->visible; + } + + /** + * @param int $id + * @return Comment + */ + public function setId(int $id) + { + $this->id = $id; + return $this; + } + + /** + * @param string $content + * @return Comment + */ + public function setContent(string $content) + { + $this->content = $content; + return $this; + } + + /** + * @param DateTime $createdAt + * @return Comment + */ + public function setCreatedAt(DateTime $createdAt) + { + $this->createdAt = clone $createdAt; + return $this; + } + + /** + * @param Article $article + * @return Comment + */ + public function setArticle(Article $article) + { + $this->article = $article; + return $this; + } + + /** + * @param User $author + * @return Comment + */ + public function setAuthor(User $author) + { + $this->author = $author; + return $this; + } + + /** + * @param bool $visible + * @return Comment + */ + public function setVisible(bool $visible) + { + $this->visible = $visible; + return $this; + } + + /** + * @return array + */ + public function jsonSerialize() + { + return [ + 'id' => $this->id, + 'content' => $this->content, + 'createdAt' => $this->createdAt, + 'author' => $this->author, + 'article' => $this->article, + 'visible' => $this->visible, + ]; + } +} \ No newline at end of file diff --git a/src/App/Entity/Traits/GetterSetter.php b/src/App/Entity/Traits/GetterSetter.php new file mode 100644 index 0000000..b5fceff --- /dev/null +++ b/src/App/Entity/Traits/GetterSetter.php @@ -0,0 +1,52 @@ + $value) { + $setter = $this->setterName($field); + if (method_exists($this, $setter)) { + $this->{$setter}($value); + } + } + + return true; + } +} \ No newline at end of file diff --git a/src/App/Entity/User.php b/src/App/Entity/User.php new file mode 100644 index 0000000..02c5d92 --- /dev/null +++ b/src/App/Entity/User.php @@ -0,0 +1,184 @@ +articles = new ArrayCollection(); + $this->comments = new ArrayCollection(); + } + + /** + * @return int + */ + public function getId() + { + return $this->id; + } + + /** + * @return string + */ + public function getName() + { + return $this->name; + } + + /** + * @return string + */ + public function getEmail() + { + return $this->email; + } + + /** + * @return Article[] + */ + public function getArticles() + { + return $this->articles; + } + + /** + * @return Comment[] + */ + public function getComments() + { + return $this->comments; + } + + /** + * @return bool + */ + public function getActive() + { + return $this->active; + } + + /** + * @param int $id + * @return User + */ + public function setId(int $id) + { + $this->id = $id; + return $this; + } + + /** + * @param string $name + * @return User + */ + public function setName(string $name) + { + $this->name = $name; + return $this; + } + + /** + * @param string $email + * @return User + */ + public function setEmail(string $email) + { + $this->email = $email; + return $this; + } + + /** + * @param Article[] $articles + * @return User + */ + public function setArticles(array $articles) + { + $this->articles = $articles; + return $this; + } + + /** + * @param Comment[] $comments + * @return User + */ + public function setComments(array $comments) + { + $this->comments = $comments; + return $this; + } + + /** + * @param bool $active + * @return User + */ + public function setActive(bool $active) + { + $this->active = $active; + return $this; + } + + /** + * @return array + */ + public function jsonSerialize() + { + return [ + 'id' => $this->id, + 'name' => $this->name, + 'email' => $this->email, + 'articles' => $this->articles, + 'comments' => $this->comments, + 'active' => $this->active, + ]; + } +} \ No newline at end of file diff --git a/src/App/Hydrator/DoctrineObject.php b/src/App/Hydrator/DoctrineObject.php new file mode 100644 index 0000000..3597166 --- /dev/null +++ b/src/App/Hydrator/DoctrineObject.php @@ -0,0 +1,595 @@ +. + */ + +namespace App\Hydrator; + +use DateTime; +use Doctrine\Common\Persistence\Mapping\ClassMetadata; +use Doctrine\Common\Persistence\ObjectManager; +use Doctrine\Common\Util\Inflector; +use InvalidArgumentException; +use RuntimeException; +use Traversable; +use Zend\Stdlib\ArrayUtils; +use Zend\Hydrator\AbstractHydrator; +use Zend\Hydrator\Filter\FilterProviderInterface; + +/** + * This hydrator has been completely refactored for DoctrineModule 0.7.0. It provides an easy and powerful way + * of extracting/hydrator objects in Doctrine, by handling most associations types. + * + * Starting from DoctrineModule 0.8.0, the hydrator can be used multiple times with different objects + * + * @license MIT + * @link http://www.doctrine-project.org/ + * @since 0.7.0 + * @author Michael Gallego + */ +class DoctrineObject extends AbstractHydrator +{ + /** + * @var ObjectManager + */ + protected $objectManager; + + /** + * @var ClassMetadata + */ + protected $metadata; + + /** + * @var bool + */ + protected $byValue = true; + + + /** + * Constructor + * + * @param ObjectManager $objectManager The ObjectManager to use + * @param bool $byValue If set to true, hydrator will always use entity's public API + */ + public function __construct(ObjectManager $objectManager, $byValue = true) + { + parent::__construct(); + + $this->objectManager = $objectManager; + $this->byValue = (bool) $byValue; + } + + /** + * Extract values from an object + * + * @param object $object + * @return array + */ + public function extract($object) + { + $this->prepare($object); + + if ($this->byValue) { + return $this->extractByValue($object); + } + + return $this->extractByReference($object); + } + + /** + * Hydrate $object with the provided $data. + * + * @param array $data + * @param object $object + * @return object + */ + public function hydrate(array $data, $object) + { + $this->prepare($object); + + if ($this->byValue) { + return $this->hydrateByValue($data, $object); + } + + return $this->hydrateByReference($data, $object); + } + + /** + * Prepare the hydrator by adding strategies to every collection valued associations + * + * @param object $object + * @return void + */ + protected function prepare($object) + { + $this->metadata = $this->objectManager->getClassMetadata(get_class($object)); + $this->prepareStrategies(); + } + + /** + * Prepare strategies before the hydrator is used + * + * @throws \InvalidArgumentException + * @return void + */ + protected function prepareStrategies() + { + $associations = $this->metadata->getAssociationNames(); + + foreach ($associations as $association) { + if ($this->metadata->isCollectionValuedAssociation($association)) { + // Add a strategy if the association has none set by user + if (!$this->hasStrategy($association)) { + if ($this->byValue) { + $this->addStrategy($association, new Strategy\AllowRemoveByValue()); + } else { + $this->addStrategy($association, new Strategy\AllowRemoveByReference()); + } + } + + $strategy = $this->getStrategy($association); + + if (!$strategy instanceof Strategy\AbstractCollectionStrategy) { + throw new InvalidArgumentException( + sprintf( + 'Strategies used for collections valued associations must inherit from ' + . 'Strategy\AbstractCollectionStrategy, %s given', + get_class($strategy) + ) + ); + } + + $strategy->setCollectionName($association) + ->setClassMetadata($this->metadata); + } + } + } + + /** + * Extract values from an object using a by-value logic (this means that it uses the entity + * API, in this case, getters) + * + * @param object $object + * @throws RuntimeException + * @return array + */ + protected function extractByValue($object) + { + $fieldNames = array_merge($this->metadata->getFieldNames(), $this->metadata->getAssociationNames()); + $methods = get_class_methods($object); + $filter = $object instanceof FilterProviderInterface + ? $object->getFilter() + : $this->filterComposite; + + $data = array(); + foreach ($fieldNames as $fieldName) { + if ($filter && !$filter->filter($fieldName)) { + continue; + } + + $getter = 'get' . Inflector::classify($fieldName); + $isser = 'is' . Inflector::classify($fieldName); + + $dataFieldName = $this->computeExtractFieldName($fieldName); + if (in_array($getter, $methods)) { + $data[$dataFieldName] = $this->extractValue($fieldName, $object->$getter(), $object); + } elseif (in_array($isser, $methods)) { + $data[$dataFieldName] = $this->extractValue($fieldName, $object->$isser(), $object); + } elseif (substr($fieldName, 0, 2) === 'is' + && ctype_upper(substr($fieldName, 2, 1)) + && in_array($fieldName, $methods)) { + $data[$dataFieldName] = $this->extractValue($fieldName, $object->$fieldName(), $object); + } + + // Unknown fields are ignored + } + + return $data; + } + + /** + * Extract values from an object using a by-reference logic (this means that values are + * directly fetched without using the public API of the entity, in this case, getters) + * + * @param object $object + * @return array + */ + protected function extractByReference($object) + { + $fieldNames = array_merge($this->metadata->getFieldNames(), $this->metadata->getAssociationNames()); + $refl = $this->metadata->getReflectionClass(); + $filter = $object instanceof FilterProviderInterface + ? $object->getFilter() + : $this->filterComposite; + + $data = array(); + foreach ($fieldNames as $fieldName) { + if ($filter && !$filter->filter($fieldName)) { + continue; + } + $reflProperty = $refl->getProperty($fieldName); + $reflProperty->setAccessible(true); + + $dataFieldName = $this->computeExtractFieldName($fieldName); + $data[$dataFieldName] = $this->extractValue($fieldName, $reflProperty->getValue($object), $object); + } + + return $data; + } + + /** + * Hydrate the object using a by-value logic (this means that it uses the entity API, in this + * case, setters) + * + * @param array $data + * @param object $object + * @throws RuntimeException + * @return object + */ + protected function hydrateByValue(array $data, $object) + { + $tryObject = $this->tryConvertArrayToObject($data, $object); + $metadata = $this->metadata; + + if (is_object($tryObject)) { + $object = $tryObject; + } + + foreach ($data as $field => $value) { + $field = $this->computeHydrateFieldName($field); + $value = $this->handleTypeConversions($value, $metadata->getTypeOfField($field)); + $setter = 'set' . Inflector::classify($field); + + if ($metadata->hasAssociation($field)) { + $target = $metadata->getAssociationTargetClass($field); + + if ($metadata->isSingleValuedAssociation($field)) { + if (! method_exists($object, $setter)) { + continue; + } + + $value = $this->toOne($target, $this->hydrateValue($field, $value, $data)); + + if (null === $value + && !current($metadata->getReflectionClass()->getMethod($setter)->getParameters())->allowsNull() + ) { + continue; + } + + $object->$setter($value); + } elseif ($metadata->isCollectionValuedAssociation($field)) { + $this->toMany($object, $field, $target, $value); + } + } else { + if (! method_exists($object, $setter)) { + continue; + } + + $object->$setter($this->hydrateValue($field, $value, $data)); + } + } + + return $object; + } + + /** + * Hydrate the object using a by-reference logic (this means that values are modified directly without + * using the public API, in this case setters, and hence override any logic that could be done in those + * setters) + * + * @param array $data + * @param object $object + * @return object + */ + protected function hydrateByReference(array $data, $object) + { + $tryObject = $this->tryConvertArrayToObject($data, $object); + $metadata = $this->metadata; + $refl = $metadata->getReflectionClass(); + + if (is_object($tryObject)) { + $object = $tryObject; + } + + foreach ($data as $field => $value) { + $field = $this->computeHydrateFieldName($field); + + // Ignore unknown fields + if (!$refl->hasProperty($field)) { + continue; + } + + $value = $this->handleTypeConversions($value, $metadata->getTypeOfField($field)); + $reflProperty = $refl->getProperty($field); + $reflProperty->setAccessible(true); + + if ($metadata->hasAssociation($field)) { + $target = $metadata->getAssociationTargetClass($field); + + if ($metadata->isSingleValuedAssociation($field)) { + $value = $this->toOne($target, $this->hydrateValue($field, $value, $data)); + $reflProperty->setValue($object, $value); + } elseif ($metadata->isCollectionValuedAssociation($field)) { + $this->toMany($object, $field, $target, $value); + } + } else { + $reflProperty->setValue($object, $this->hydrateValue($field, $value, $data)); + } + } + + return $object; + } + + /** + * This function tries, given an array of data, to convert it to an object if the given array contains + * an identifier for the object. This is useful in a context of updating existing entities, without ugly + * tricks like setting manually the existing id directly into the entity + * + * @param array $data The data that may contain identifiers keys + * @param object $object + * @return object + */ + protected function tryConvertArrayToObject($data, $object) + { + $metadata = $this->metadata; + $identifierNames = $metadata->getIdentifierFieldNames($object); + $identifierValues = array(); + + if (empty($identifierNames)) { + return $object; + } + + foreach ($identifierNames as $identifierName) { + if (!isset($data[$identifierName])) { + return $object; + } + + $identifierValues[$identifierName] = $data[$identifierName]; + } + + return $this->find($identifierValues, $metadata->getName()); + } + + /** + * Handle ToOne associations + * + * When $value is an array but is not the $target's identifiers, $value is + * most likely an array of fieldset data. The identifiers will be determined + * and a target instance will be initialized and then hydrated. The hydrated + * target will be returned. + * + * @param string $target + * @param mixed $value + * @return object + */ + protected function toOne($target, $value) + { + $metadata = $this->objectManager->getClassMetadata($target); + + if (is_array($value) && array_keys($value) != $metadata->getIdentifier()) { + // $value is most likely an array of fieldset data + $identifiers = array_intersect_key( + $value, + array_flip($metadata->getIdentifier()) + ); + $object = $this->find($identifiers, $target) ?: new $target; + return $this->hydrate($value, $object); + } + + return $this->find($value, $target); + } + + /** + * Handle ToMany associations. In proper Doctrine design, Collections should not be swapped, so + * collections are always handled by reference. Internally, every collection is handled using specials + * strategies that inherit from AbstractCollectionStrategy class, and that add or remove elements but without + * changing the collection of the object + * + * @param object $object + * @param mixed $collectionName + * @param string $target + * @param mixed $values + * + * @throws \InvalidArgumentException + * + * @return void + */ + protected function toMany($object, $collectionName, $target, $values) + { + $metadata = $this->objectManager->getClassMetadata(ltrim($target, '\\')); + $identifier = $metadata->getIdentifier(); + + if (!is_array($values) && !$values instanceof Traversable) { + $values = (array)$values; + } + + $collection = array(); + + // If the collection contains identifiers, fetch the objects from database + foreach ($values as $value) { + + if ($value instanceof $target) { + // assumes modifications have already taken place in object + $collection[] = $value; + continue; + } elseif (empty($value)) { + // assumes no id and retrieves new $target + $collection[] = $this->find($value, $target); + continue; + } + + $find = array(); + if (is_array($identifier)) { + foreach ($identifier as $field) { + switch (gettype($value)) { + case 'object': + $getter = 'get' . ucfirst($field); + if (method_exists($value, $getter)) { + $find[$field] = $value->$getter(); + } elseif (property_exists($value, $field)) { + $find[$field] = $value->$field; + } + break; + case 'array': + if (array_key_exists($field, $value) && $value[$field] != null) { + $find[$field] = $value[$field]; + unset($value[$field]); // removed identifier from persistable data + } + break; + default: + $find[$field] = $value; + break; + } + } + } + + if (!empty($find) && $found = $this->find($find, $target)) { + $collection[] = (is_array($value)) ? $this->hydrate($value, $found) : $found; + } else { + $collection[] = (is_array($value)) ? $this->hydrate($value, new $target) : new $target; + } + } + + $collection = array_filter( + $collection, + function ($item) { + return null !== $item; + } + ); + + // Set the object so that the strategy can extract the Collection from it + + /** @var \DoctrineModule\Stdlib\Hydrator\Strategy\AbstractCollectionStrategy $collectionStrategy */ + $collectionStrategy = $this->getStrategy($collectionName); + $collectionStrategy->setObject($object); + + // We could directly call hydrate method from the strategy, but if people want to override + // hydrateValue function, they can do it and do their own stuff + $this->hydrateValue($collectionName, $collection, $values); + } + + /** + * Handle various type conversions that should be supported natively by Doctrine (like DateTime) + * + * @param mixed $value + * @param string $typeOfField + * @return DateTime + */ + protected function handleTypeConversions($value, $typeOfField) + { + switch ($typeOfField) { + case 'datetimetz': + case 'datetime': + case 'time': + case 'date': + if ('' === $value) { + return null; + } + + if (is_int($value)) { + $dateTime = new DateTime(); + $dateTime->setTimestamp($value); + $value = $dateTime; + } elseif (is_string($value)) { + $value = new DateTime($value); + } + + break; + default: + } + + return $value; + } + + /** + * Find an object by a given target class and identifier + * + * @param mixed $identifiers + * @param string $targetClass + * + * @return object|null + */ + protected function find($identifiers, $targetClass) + { + if ($identifiers instanceof $targetClass) { + return $identifiers; + } + + if ($this->isNullIdentifier($identifiers)) { + return null; + } + + return $this->objectManager->find($targetClass, $identifiers); + } + + /** + * Verifies if a provided identifier is to be considered null + * + * @param mixed $identifier + * + * @return bool + */ + private function isNullIdentifier($identifier) + { + if (null === $identifier) { + return true; + } + + if ($identifier instanceof Traversable || is_array($identifier)) { + $nonNullIdentifiers = array_filter( + ArrayUtils::iteratorToArray($identifier), + function ($value) { + return null !== $value; + } + ); + + return empty($nonNullIdentifiers); + } + + return false; + } + + /** + * Applies the naming strategy if there is one set + * + * @param string $field + * + * @return string + */ + protected function computeHydrateFieldName($field) + { + if ($this->hasNamingStrategy()) { + $field = $this->getNamingStrategy()->hydrate($field); + } + return $field; + } + + /** + * Applies the naming strategy if there is one set + * + * @param string $field + * + * @return string + */ + protected function computeExtractFieldName($field) + { + if ($this->hasNamingStrategy()) { + $field = $this->getNamingStrategy()->extract($field); + } + return $field; + } +} diff --git a/src/App/Hydrator/DoctrineObjectFactory.php b/src/App/Hydrator/DoctrineObjectFactory.php new file mode 100644 index 0000000..08c4ee5 --- /dev/null +++ b/src/App/Hydrator/DoctrineObjectFactory.php @@ -0,0 +1,15 @@ +get('doctrine.entity_manager.orm_default'); + return new DoctrineObject($em); + } +} \ No newline at end of file diff --git a/src/App/Hydrator/Filter/PropertyName.php b/src/App/Hydrator/Filter/PropertyName.php new file mode 100644 index 0000000..628bd85 --- /dev/null +++ b/src/App/Hydrator/Filter/PropertyName.php @@ -0,0 +1,66 @@ +. + */ + +namespace App\Hydrator\Filter; + +use Zend\Hydrator\Filter\FilterInterface; + +/** + * Provides a filter to restrict returned fields by whitelisting or + * blacklisting property names. + * + * @license MIT + * @link http://www.doctrine-project.org/ + * @author Liam O'Boyle + */ +class PropertyName implements FilterInterface +{ + /** + * The propteries to exclude. + * + * @var array + */ + protected $properties = array(); + + /** + * Either an exclude or an include. + * + * @var bool + */ + protected $exclude = null; + + /** + * @param [ string | array ] $properties The properties to exclude or include. + * @param bool $exclude If the method should be excluded + */ + public function __construct($properties, $exclude = true) + { + $this->exclude = $exclude; + $this->properties = is_array($properties) + ? $properties + : array($properties); + } + + public function filter($property) + { + return in_array($property, $this->properties) + ? !$this->exclude + : $this->exclude; + } +} diff --git a/src/App/Hydrator/Strategy/AbstractCollectionStrategy.php b/src/App/Hydrator/Strategy/AbstractCollectionStrategy.php new file mode 100644 index 0000000..37e6738 --- /dev/null +++ b/src/App/Hydrator/Strategy/AbstractCollectionStrategy.php @@ -0,0 +1,190 @@ +. + */ + +namespace App\Hydrator\Strategy; + +use InvalidArgumentException; +use Doctrine\Common\Collections\Collection; +use Doctrine\Common\Persistence\Mapping\ClassMetadata; +use Zend\Hydrator\Strategy\StrategyInterface; + +/** + * @license MIT + * @link http://www.doctrine-project.org/ + * @since 0.7.0 + * @author Michael Gallego + */ +abstract class AbstractCollectionStrategy implements StrategyInterface +{ + /** + * @var string + */ + protected $collectionName; + + /** + * @var ClassMetadata + */ + protected $metadata; + + /** + * @var object + */ + protected $object; + + + /** + * Set the name of the collection + * + * @param string $collectionName + * @return AbstractCollectionStrategy + */ + public function setCollectionName($collectionName) + { + $this->collectionName = (string) $collectionName; + return $this; + } + + /** + * Get the name of the collection + * + * @return string + */ + public function getCollectionName() + { + return $this->collectionName; + } + + /** + * Set the class metadata + * + * @param ClassMetadata $classMetadata + * @return AbstractCollectionStrategy + */ + public function setClassMetadata(ClassMetadata $classMetadata) + { + $this->metadata = $classMetadata; + return $this; + } + + /** + * Get the class metadata + * + * @return ClassMetadata + */ + public function getClassMetadata() + { + return $this->metadata; + } + + /** + * Set the object + * + * @param object $object + * + * @throws \InvalidArgumentException + * + * @return AbstractCollectionStrategy + */ + public function setObject($object) + { + if (!is_object($object)) { + throw new InvalidArgumentException( + sprintf('The parameter given to setObject method of %s class is not an object', get_called_class()) + ); + } + + $this->object = $object; + return $this; + } + + /** + * Get the object + * + * @return object + */ + public function getObject() + { + return $this->object; + } + + /** + * {@inheritDoc} + */ + public function extract($value) + { + return $value; + } + + /** + * Return the collection by value (using the public API) + * + * @throws \InvalidArgumentException + * + * @return Collection + */ + protected function getCollectionFromObjectByValue() + { + $object = $this->getObject(); + $getter = 'get' . ucfirst($this->getCollectionName()); + + if (!method_exists($object, $getter)) { + throw new InvalidArgumentException( + sprintf( + 'The getter %s to access collection %s in object %s does not exist', + $getter, + $this->getCollectionName(), + get_class($object) + ) + ); + } + + return $object->$getter(); + } + + /** + * Return the collection by reference (not using the public API) + * + * @return Collection + */ + protected function getCollectionFromObjectByReference() + { + $object = $this->getObject(); + $refl = $this->getClassMetadata()->getReflectionClass(); + $reflProperty = $refl->getProperty($this->getCollectionName()); + + $reflProperty->setAccessible(true); + + return $reflProperty->getValue($object); + } + + + /** + * This method is used internally by array_udiff to check if two objects are equal, according to their + * SPL hash. This is needed because the native array_diff only compare strings + * + * @param object $a + * @param object $b + * + * @return int + */ + protected function compareObjects($a, $b) + { + return strcmp(spl_object_hash($a), spl_object_hash($b)); + } +} diff --git a/src/App/Hydrator/Strategy/AllowRemoveByReference.php b/src/App/Hydrator/Strategy/AllowRemoveByReference.php new file mode 100644 index 0000000..3e483c2 --- /dev/null +++ b/src/App/Hydrator/Strategy/AllowRemoveByReference.php @@ -0,0 +1,58 @@ +. + */ + +namespace App\Hydrator\Strategy; + +/** + * When this strategy is used for Collections, if the new collection does not contain elements that are present in + * the original collection, then this strategy remove elements from the original collection. For instance, if the + * collection initially contains elements A and B, and that the new collection contains elements B and C, then the + * final collection will contain elements B and C (while element A will be asked to be removed). + * + * This strategy is by reference, this means it won't use public API to add/remove elements to the collection + * + * @license MIT + * @link http://www.doctrine-project.org/ + * @since 0.7.0 + * @author Michael Gallego + */ +class AllowRemoveByReference extends AbstractCollectionStrategy +{ + /** + * {@inheritDoc} + */ + public function hydrate($value) + { + $collection = $this->getCollectionFromObjectByReference(); + $collectionArray = $collection->toArray(); + + $toAdd = array_udiff($value, $collectionArray, array($this, 'compareObjects')); + $toRemove = array_udiff($collectionArray, $value, array($this, 'compareObjects')); + + foreach ($toAdd as $element) { + $collection->add($element); + } + + foreach ($toRemove as $element) { + $collection->removeElement($element); + } + + return $collection; + } +} diff --git a/src/App/Hydrator/Strategy/AllowRemoveByValue.php b/src/App/Hydrator/Strategy/AllowRemoveByValue.php new file mode 100644 index 0000000..6ebf9f7 --- /dev/null +++ b/src/App/Hydrator/Strategy/AllowRemoveByValue.php @@ -0,0 +1,76 @@ +. + */ + +namespace App\Hydrator\Strategy; + +use Doctrine\Common\Collections\Collection; +use LogicException; +use Doctrine\Common\Collections\ArrayCollection; + +/** + * When this strategy is used for Collections, if the new collection does not contain elements that are present in + * the original collection, then this strategy remove elements from the original collection. For instance, if the + * collection initially contains elements A and B, and that the new collection contains elements B and C, then the + * final collection will contain elements B and C (while element A will be asked to be removed). + * + * This strategy is by value, this means it will use the public API (in this case, adder and remover) + * + * @license MIT + * @link http://www.doctrine-project.org/ + * @since 0.7.0 + * @author Michael Gallego + */ +class AllowRemoveByValue extends AbstractCollectionStrategy +{ + /** + * {@inheritDoc} + */ + public function hydrate($value) + { + // AllowRemove strategy need "adder" and "remover" + $adder = 'add' . ucfirst($this->collectionName); + $remover = 'remove' . ucfirst($this->collectionName); + + if (!method_exists($this->object, $adder) || !method_exists($this->object, $remover)) { + throw new LogicException( + sprintf( + 'AllowRemove strategy for DoctrineModule hydrator requires both %s and %s to be defined in %s + entity domain code, but one or both seem to be missing', + $adder, + $remover, + get_class($this->object) + ) + ); + } + + $collection = $this->getCollectionFromObjectByValue(); + + if ($collection instanceof Collection) { + $collection = $collection->toArray(); + } + + $toAdd = new ArrayCollection(array_udiff($value, $collection, array($this, 'compareObjects'))); + $toRemove = new ArrayCollection(array_udiff($collection, $value, array($this, 'compareObjects'))); + + $this->object->$adder($toAdd); + $this->object->$remover($toRemove); + + return $collection; + } +} diff --git a/src/App/Hydrator/Strategy/DisallowRemoveByReference.php b/src/App/Hydrator/Strategy/DisallowRemoveByReference.php new file mode 100644 index 0000000..4222f90 --- /dev/null +++ b/src/App/Hydrator/Strategy/DisallowRemoveByReference.php @@ -0,0 +1,53 @@ +. + */ + +namespace App\Hydrator\Strategy; + +/** + * When this strategy is used for Collections, if the new collection does not contain elements that are present in + * the original collection, then this strategy will not remove those elements. At most, it will add new elements. For + * instance, if the collection initially contains elements A and B, and that the new collection contains elements B + * and C, then the final collection will contain elements A, B and C. + * + * This strategy is by reference, this means it won't use the public API to remove elements + * + * @license MIT + * @link http://www.doctrine-project.org/ + * @since 0.7.0 + * @author Michael Gallego + */ +class DisallowRemoveByReference extends AbstractCollectionStrategy +{ + /** + * {@inheritDoc} + */ + public function hydrate($value) + { + $collection = $this->getCollectionFromObjectByReference(); + $collectionArray = $collection->toArray(); + + $toAdd = array_udiff($value, $collectionArray, array($this, 'compareObjects')); + + foreach ($toAdd as $element) { + $collection->add($element); + } + + return $collection; + } +} diff --git a/src/App/Hydrator/Strategy/DisallowRemoveByValue.php b/src/App/Hydrator/Strategy/DisallowRemoveByValue.php new file mode 100644 index 0000000..2e6019b --- /dev/null +++ b/src/App/Hydrator/Strategy/DisallowRemoveByValue.php @@ -0,0 +1,72 @@ +. + */ + +namespace App\Hydrator\Strategy; + +use Doctrine\Common\Collections\Collection; +use LogicException; +use Doctrine\Common\Collections\ArrayCollection; + +/** + * When this strategy is used for Collections, if the new collection does not contain elements that are present in + * the original collection, then this strategy will not remove those elements. At most, it will add new elements. For + * instance, if the collection initially contains elements A and B, and that the new collection contains elements B + * and C, then the final collection will contain elements A, B and C. + * + * This strategy is by value, this means it will use the public API (in this case, remover) + * + * @license MIT + * @link http://www.doctrine-project.org/ + * @since 0.7.0 + * @author Michael Gallego + */ +class DisallowRemoveByValue extends AbstractCollectionStrategy +{ + /** + * {@inheritDoc} + */ + public function hydrate($value) + { + // AllowRemove strategy need "adder" + $adder = 'add' . ucfirst($this->collectionName); + + if (!method_exists($this->object, $adder)) { + throw new LogicException( + sprintf( + 'DisallowRemove strategy for DoctrineModule hydrator requires %s to + be defined in %s entity domain code, but it seems to be missing', + $adder, + get_class($this->object) + ) + ); + } + + $collection = $this->getCollectionFromObjectByValue(); + + if ($collection instanceof Collection) { + $collection = $collection->toArray(); + } + + $toAdd = new ArrayCollection(array_udiff($value, $collection, array($this, 'compareObjects'))); + + $this->object->$adder($toAdd); + + return $collection; + } +} diff --git a/templates/.gitkeep b/templates/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/test/AppTest/Action/HomePageActionTest.php b/test/AppTest/Action/HomePageActionTest.php new file mode 100644 index 0000000..3a083c7 --- /dev/null +++ b/test/AppTest/Action/HomePageActionTest.php @@ -0,0 +1,28 @@ +router = $this->prophesize(RouterInterface::class); + } + + public function testResponse() + { + $homePage = new HomePageAction($this->router->reveal(), null); + $response = $homePage(new ServerRequest(['/']), new Response(), function () { + }); + + $this->assertTrue($response instanceof Response); + } +} diff --git a/test/AppTest/Action/HomePageFactoryTest.php b/test/AppTest/Action/HomePageFactoryTest.php new file mode 100644 index 0000000..3a98fcd --- /dev/null +++ b/test/AppTest/Action/HomePageFactoryTest.php @@ -0,0 +1,50 @@ +container = $this->prophesize(ContainerInterface::class); + $router = $this->prophesize(RouterInterface::class); + + $this->container->get(RouterInterface::class)->willReturn($router); + } + + public function testFactoryWithoutTemplate() + { + $factory = new HomePageFactory(); + $this->container->has(TemplateRendererInterface::class)->willReturn(false); + + $this->assertTrue($factory instanceof HomePageFactory); + + $homePage = $factory($this->container->reveal()); + + $this->assertTrue($homePage instanceof HomePageAction); + } + + public function testFactoryWithTemplate() + { + $factory = new HomePageFactory(); + $this->container->has(TemplateRendererInterface::class)->willReturn(true); + $this->container + ->get(TemplateRendererInterface::class) + ->willReturn($this->prophesize(TemplateRendererInterface::class)); + + $this->assertTrue($factory instanceof HomePageFactory); + + $homePage = $factory($this->container->reveal()); + + $this->assertTrue($homePage instanceof HomePageAction); + } +} diff --git a/test/AppTest/Action/PingActionTest.php b/test/AppTest/Action/PingActionTest.php new file mode 100644 index 0000000..d0911f5 --- /dev/null +++ b/test/AppTest/Action/PingActionTest.php @@ -0,0 +1,22 @@ +getBody()); + + $this->assertTrue($response instanceof Response); + $this->assertTrue($response instanceof Response\JsonResponse); + $this->assertTrue(isset($json->ack)); + } +}