public function save() {
parent::save();
- $htmlInputProcessor = WCF::getDIContainer()->make(HtmlInputProcessor::class);
+ $htmlInputProcessor = new HtmlInputProcessor();
$this->text = $htmlInputProcessor->process($this->text);
// parse URLs
/**
* Basis class for singleton classes.
- *
+ *
* @author Alexander Ebert
* @copyright 2001-2015 WoltLab GmbH
* @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
* @package com.woltlab.wcf
* @subpackage system
* @category Community Framework
- * @deprecated 2.2
*/
abstract class SingletonFactory {
+ /**
+ * list of singletons
+ * @var SingletonFactory[]
+ */
+ protected static $__singletonObjects = array();
+
/**
* Singletons do not support a public constructor. Override init() if
* your class needs to initialize components on creation.
*/
- public function __construct() {
+ protected final function __construct() {
$this->init();
}
/**
* Returns an unique instance of current child class.
- *
+ *
* @return static
*/
public static final function getInstance() {
- return WCF::getDIContainer()->get(get_called_class());
+ $className = get_called_class();
+ if (!array_key_exists($className, self::$__singletonObjects)) {
+ self::$__singletonObjects[$className] = null;
+ self::$__singletonObjects[$className] = new $className();
+ }
+ else if (self::$__singletonObjects[$className] === null) {
+ throw new SystemException("Infinite loop detected while trying to retrieve object for '".$className."'");
+ }
+
+ return self::$__singletonObjects[$className];
+ }
+
+ /**
+ * Returns whether this singleton is already initialized.
+ *
+ * @return boolean
+ */
+ public static final function isInitialized() {
+ $className = get_called_class();
+
+ return isset(self::$__singletonObjects[$className]);
}
}
<?php
namespace wcf\system;
-use DI\ContainerBuilder;
use wcf\data\application\Application;
use wcf\data\option\OptionEditor;
use wcf\data\package\Package;
use wcf\data\package\PackageCache;
use wcf\data\package\PackageEditor;
use wcf\system\application\ApplicationHandler;
+use wcf\system\application\IApplication;
use wcf\system\cache\builder\CoreObjectCacheBuilder;
use wcf\system\cache\builder\PackageUpdateCacheBuilder;
use wcf\system\cronjob\CronjobScheduler;
class WCF {
/**
* list of currently loaded applications
- * @var array<\wcf\data\application\Application>
+ * @var Application[]
*/
protected static $applications = array();
*/
protected static $dbObj = null;
- /**
- * dependency injection container
- * @var \DI\Container
- */
- protected static $diContainer = null;
-
/**
* language object
* @var \wcf\data\language\Language
// define tmp directory
if (!defined('TMP_DIR')) define('TMP_DIR', FileUtil::getTempFolder());
- $builder = new ContainerBuilder();
- self::$diContainer = $builder->build();
-
// start initialization
$this->initDB();
$this->loadOptions();
EventHandler::getInstance()->fireAction($this, 'initialized');
}
- /**
- * Returns the dependency injection container.
- *
- * @return \DI\Container
- */
- public static final function getDIContainer() {
- return self::$diContainer;
- }
-
/**
* Flushes the output, closes the session, performs background tasks and more.
*
* Starts the session system.
*/
protected function initSession() {
- $factory = self::$diContainer->get(SessionFactory::class);
+ $factory = new SessionFactory();
$factory->load();
- self::$sessionObj = self::$diContainer->get(SessionHandler::class);
+ self::$sessionObj = SessionHandler::getInstance();
self::$sessionObj->setHasValidCookie($factory->hasValidCookie());
}
mb_language('uni');
// get language
- self::$languageObj = self::$diContainer->get(LanguageFactory::class)->getUserLanguage(self::getSession()->getLanguageID());
+ self::$languageObj = LanguageFactory::getInstance()->getUserLanguage(self::getSession()->getLanguageID());
}
/**
* Initialises the template engine.
*/
protected function initTPL() {
- self::$tplObj = self::$diContainer->get(TemplateEngine::class);
+ self::$tplObj = TemplateEngine::getInstance();
self::getTPL()->setLanguageID(self::getLanguage()->languageID);
$this->assignDefaultTemplateVariables();
self::getSession()->setStyleID(intval($_REQUEST['styleID']));
}
- $styleHandler = self::$diContainer->get(StyleHandler::class);
+ $styleHandler = StyleHandler::getInstance();
$styleHandler->changeStyle(self::getSession()->getStyleID());
}
// step 2) run each application
if (!class_exists('wcf\system\WCFACP', false)) {
+ /** @var IApplication $application */
foreach ($loadedApplications as $application) {
$application->__run();
}
<?php
namespace wcf\system;
-use DI\ContainerBuilder;
use wcf\acp\form\MasterPasswordForm;
use wcf\acp\form\MasterPasswordInitForm;
use wcf\system\application\ApplicationHandler;
// define tmp directory
if (!defined('TMP_DIR')) define('TMP_DIR', FileUtil::getTempFolder());
- $builder = new ContainerBuilder();
- self::$diContainer = $builder->build();
-
// start initialization
$this->initDB();
$this->loadOptions();
<?php
namespace wcf\system;
-use DI\ContainerBuilder;
use wcf\data\language\LanguageEditor;
use wcf\data\language\SetupLanguage;
use wcf\data\package\installation\queue\PackageInstallationQueueEditor;
use wcf\system\session\SessionHandler;
use wcf\system\setup\Installer;
use wcf\system\template\SetupTemplateEngine;
-use wcf\system\Regex;
-use wcf\system\WCF;
use wcf\util\DirectoryUtil;
use wcf\util\FileUtil;
use wcf\util\StringUtil;
public function __construct() {
@set_time_limit(0);
- require('api/autoload.php');
- $builder = new ContainerBuilder();
- self::$diContainer = $builder->build();
-
$this->getDeveloperMode();
$this->getLanguageSelection();
$this->getWCFDir();
}
// login as admin
- $factory = WCF::getDIContainer()->make(ACPSessionFactory::class);
+ $factory = new ACPSessionFactory();
$factory->load();
SessionHandler::getInstance()->changeUser($admin);
"vendor-dir": "./"
},
"require": {
- "ezyang/htmlpurifier": "4.7.*",
- "php-di/php-di": "5.1.*"
+ "ezyang/htmlpurifier": "4.7.*"
}
}
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file",
"This file is @generated automatically"
],
- "hash": "cd00e4c8e538bb4769bfed7eddcb4e28",
- "content-hash": "6867afc3a51e9cdeb9a855131601864e",
+ "hash": "7364a2d47c47ff382d4617f4ac22e35c",
+ "content-hash": "02969f5fb096600e5baaf84af039646e",
"packages": [
{
"name": "container-interop/container-interop",
],
"time": "2015-10-22 19:49:23"
},
- {
- "name": "php-di/php-di",
- "version": "5.1.0",
- "source": {
- "type": "git",
- "url": "https://github.com/PHP-DI/PHP-DI.git",
- "reference": "f4a8088fa4eb480ee66c51b5ee4e4e30cce78489"
- },
- "dist": {
- "type": "zip",
- "url": "https://api.github.com/repos/PHP-DI/PHP-DI/zipball/f4a8088fa4eb480ee66c51b5ee4e4e30cce78489",
- "reference": "f4a8088fa4eb480ee66c51b5ee4e4e30cce78489",
- "shasum": ""
- },
- "require": {
- "container-interop/container-interop": "~1.0",
- "php": ">=5.4.0",
- "php-di/invoker": "^1.0.1",
- "php-di/phpdoc-reader": "~2.0"
- },
- "replace": {
- "mnapoli/php-di": "*"
- },
- "require-dev": {
- "doctrine/annotations": "~1.2",
- "doctrine/cache": "~1.4",
- "mnapoli/phpunit-easymock": "~0.1.4",
- "ocramius/proxy-manager": "~1.0",
- "phpunit/phpunit": "~4.5"
- },
- "suggest": {
- "doctrine/annotations": "Install it if you want to use annotations (version ~1.2)",
- "doctrine/cache": "Install it if you want to use the cache (version ~1.4)",
- "ocramius/proxy-manager": "Install it if you want to use lazy injection (version ~1.0)"
- },
- "type": "library",
- "autoload": {
- "psr-4": {
- "DI\\": "src/DI/"
- },
- "files": [
- "src/DI/functions.php"
- ]
- },
- "notification-url": "https://packagist.org/downloads/",
- "license": [
- "MIT"
- ],
- "description": "The dependency injection container for humans",
- "homepage": "http://php-di.org/",
- "keywords": [
- "container",
- "dependency injection",
- "di"
- ],
- "time": "2015-09-08 08:56:29"
- },
{
"name": "php-di/phpdoc-reader",
"version": "2.0.0",
$baseDir = $vendorDir;
return array(
- $vendorDir . '/php-di/php-di/src/DI/functions.php',
$vendorDir . '/ezyang/htmlpurifier/library/HTMLPurifier.composer.php',
);
'PhpDocReader\\' => array($vendorDir . '/php-di/phpdoc-reader/src/PhpDocReader'),
'Invoker\\' => array($vendorDir . '/php-di/invoker/src'),
'Interop\\Container\\' => array($vendorDir . '/container-interop/container-interop/src/Interop/Container'),
- 'DI\\' => array($vendorDir . '/php-di/php-di/src/DI'),
);
"invoker"
]
},
- {
- "name": "php-di/php-di",
- "version": "5.1.0",
- "version_normalized": "5.1.0.0",
- "source": {
- "type": "git",
- "url": "https://github.com/PHP-DI/PHP-DI.git",
- "reference": "f4a8088fa4eb480ee66c51b5ee4e4e30cce78489"
- },
- "dist": {
- "type": "zip",
- "url": "https://api.github.com/repos/PHP-DI/PHP-DI/zipball/f4a8088fa4eb480ee66c51b5ee4e4e30cce78489",
- "reference": "f4a8088fa4eb480ee66c51b5ee4e4e30cce78489",
- "shasum": ""
- },
- "require": {
- "container-interop/container-interop": "~1.0",
- "php": ">=5.4.0",
- "php-di/invoker": "^1.0.1",
- "php-di/phpdoc-reader": "~2.0"
- },
- "replace": {
- "mnapoli/php-di": "*"
- },
- "require-dev": {
- "doctrine/annotations": "~1.2",
- "doctrine/cache": "~1.4",
- "mnapoli/phpunit-easymock": "~0.1.4",
- "ocramius/proxy-manager": "~1.0",
- "phpunit/phpunit": "~4.5"
- },
- "suggest": {
- "doctrine/annotations": "Install it if you want to use annotations (version ~1.2)",
- "doctrine/cache": "Install it if you want to use the cache (version ~1.4)",
- "ocramius/proxy-manager": "Install it if you want to use lazy injection (version ~1.0)"
- },
- "time": "2015-09-08 08:56:29",
- "type": "library",
- "installation-source": "dist",
- "autoload": {
- "psr-4": {
- "DI\\": "src/DI/"
- },
- "files": [
- "src/DI/functions.php"
- ]
- },
- "notification-url": "https://packagist.org/downloads/",
- "license": [
- "MIT"
- ],
- "description": "The dependency injection container for humans",
- "homepage": "http://php-di.org/",
- "keywords": [
- "container",
- "dependency injection",
- "di"
- ]
- },
{
"name": "ezyang/htmlpurifier",
"version": "v4.7.0",
+++ /dev/null
-composer.lock
-composer.phar
-/vendor/
+++ /dev/null
-The MIT License (MIT)
-
-Copyright (c) 2013 container-interop
-
-Permission is hereby granted, free of charge, to any person obtaining a copy of
-this software and associated documentation files (the "Software"), to deal in
-the Software without restriction, including without limitation the rights to
-use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
-the Software, and to permit persons to whom the Software is furnished to do so,
-subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
-FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
-COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
-IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
-CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+++ /dev/null
-# Container Interoperability
-
-[![Latest Stable Version](https://poser.pugx.org/container-interop/container-interop/v/stable.png)](https://packagist.org/packages/container-interop/container-interop)
-
-*container-interop* tries to identify and standardize features in *container* objects (service locators,
-dependency injection containers, etc.) to achieve interopererability.
-
-Through discussions and trials, we try to create a standard, made of common interfaces but also recommendations.
-
-If PHP projects that provide container implementations begin to adopt these common standards, then PHP
-applications and projects that use containers can depend on the common interfaces instead of specific
-implementations. This facilitates a high-level of interoperability and flexibility that allows users to consume
-*any* container implementation that can be adapted to these interfaces.
-
-The work done in this project is not officially endorsed by the [PHP-FIG](http://www.php-fig.org/), but it is being
-worked on by members of PHP-FIG and other good developers. We adhere to the spirit and ideals of PHP-FIG, and hope
-this project will pave the way for one or more future PSRs.
-
-
-## Installation
-
-You can install this package through Composer:
-
-```json
-{
- "require": {
- "container-interop/container-interop": "~1.0"
- }
-}
-```
-
-The packages adheres to the [SemVer](http://semver.org/) specification, and there will be full backward compatibility
-between minor versions.
-
-## Standards
-
-### Available
-
-- [`ContainerInterface`](src/Interop/Container/ContainerInterface.php).
-[Description](docs/ContainerInterface.md) [Meta Document](docs/ContainerInterface-meta.md).
-Describes the interface of a container that exposes methods to read its entries.
-- [*Delegate lookup feature*](docs/Delegate-lookup.md).
-[Meta Document](docs/Delegate-lookup-meta.md).
-Describes the ability for a container to delegate the lookup of its dependencies to a third-party container. This
-feature lets several containers work together in a single application.
-
-### Proposed
-
-View open [request for comments](https://github.com/container-interop/container-interop/labels/RFC)
-
-## Compatible projects
-
-### Projects implementing `ContainerInterface`
-
-- [Acclimate](https://github.com/jeremeamia/acclimate-container)
-- [dcp-di](https://github.com/estelsmith/dcp-di)
-- [Mouf](http://mouf-php.com)
-- [Njasm Container](https://github.com/njasm/container)
-- [PHP-DI](http://php-di.org)
-- [PimpleInterop](https://github.com/moufmouf/pimple-interop)
-- [XStatic](https://github.com/jeremeamia/xstatic)
-
-### Projects implementing the *delegate lookup* feature
-
-- [Mouf](http://mouf-php.com)
-- [PHP-DI](http://php-di.org)
-- [PimpleInterop](https://github.com/moufmouf/pimple-interop)
-
-## Workflow
-
-Everyone is welcome to join and contribute.
-
-The general workflow looks like this:
-
-1. Someone opens a discussion (GitHub issue) to suggest an interface
-1. Feedback is gathered
-1. The interface is added to a development branch
-1. We release alpha versions so that the interface can be experimented with
-1. Discussions and edits ensue until the interface is deemed stable by a general consensus
-1. A new minor version of the package is released
-
-We try to not break BC by creating new interfaces instead of editing existing ones.
-
-While we currently work on interfaces, we are open to anything that might help towards interoperability, may that
-be code, best practices, etc.
+++ /dev/null
-{
- "name": "container-interop/container-interop",
- "type": "library",
- "description": "Promoting the interoperability of container objects (DIC, SL, etc.)",
- "license": "MIT",
- "autoload": {
- "psr-4": {
- "Interop\\Container\\": "src/Interop/Container/"
- }
- }
-}
+++ /dev/null
-# ContainerInterface Meta Document
-
-## Introduction
-
-This document describes the process and discussions that lead to the `ContainerInterface`.
-Its goal is to explain the reasons behind each decision.
-
-## Goal
-
-The goal set by `ContainerInterface` is to standardize how frameworks and libraries make use of a
-container to obtain objects and parameters.
-
-By standardizing such a behavior, frameworks and libraries using the `ContainerInterface`
-could work with any compatible container.
-That would allow end users to choose their own container based on their own preferences.
-
-It is important to distinguish the two usages of a container:
-
-- configuring entries
-- fetching entries
-
-Most of the time, those two sides are not used by the same party.
-While it is often end users who tend to configure entries, it is generally the framework that fetch
-entries to build the application.
-
-This is why this interface focuses only on how entries can be fetched from a container.
-
-## Interface name
-
-The interface name has been thoroughly discussed and was decided by a vote.
-
-The list of options considered with their respective votes are:
-
-- `ContainerInterface`: +8
-- `ProviderInterface`: +2
-- `LocatorInterface`: 0
-- `ReadableContainerInterface`: -5
-- `ServiceLocatorInterface`: -6
-- `ObjectFactory`: -6
-- `ObjectStore`: -8
-- `ConsumerInterface`: -9
-
-[Full results of the vote](https://github.com/container-interop/container-interop/wiki/%231-interface-name:-Vote)
-
-The complete discussion can be read in [the issue #1](https://github.com/container-interop/container-interop/issues/1).
-
-## Interface methods
-
-The choice of which methods the interface would contain was made after a statistical analysis of existing containers.
-The results of this analysis are available [in this document](https://gist.github.com/mnapoli/6159681).
-
-The summary of the analysis showed that:
-
-- all containers offer a method to get an entry by its id
-- a large majority name such method `get()`
-- for all containers, the `get()` method has 1 mandatory parameter of type string
-- some containers have an optional additional argument for `get()`, but it doesn't same the same purpose between containers
-- a large majority of the containers offer a method to test if it can return an entry by its id
-- a majority name such method `has()`
-- for all containers offering `has()`, the method has exactly 1 parameter of type string
-- a large majority of the containers throw an exception rather than returning null when an entry is not found in `get()`
-- a large majority of the containers don't implement `ArrayAccess`
-
-The question of whether to include methods to define entries has been discussed in
-[issue #1](https://github.com/container-interop/container-interop/issues/1).
-It has been judged that such methods do not belong in the interface described here because it is out of its scope
-(see the "Goal" section).
-
-As a result, the `ContainerInterface` contains two methods:
-
-- `get()`, returning anything, with one mandatory string parameter. Should throw an exception if the entry is not found.
-- `has()`, returning a boolean, with one mandatory string parameter.
-
-### Number of parameters in `get()` method
-
-While `ContainerInterface` only defines one mandatory parameter in `get()`, it is not incompatible with
-existing containers that have additional optional parameters. PHP allows an implementation to offer more parameters
-as long as they are optional, because the implementation *does* satisfy the interface.
-
-This issue has been discussed in [issue #6](https://github.com/container-interop/container-interop/issues/6).
-
-### Type of the `$id` parameter
-
-The type of the `$id` parameter in `get()` and `has()` has been discussed in
-[issue #6](https://github.com/container-interop/container-interop/issues/6).
-While `string` is used in all the containers that were analyzed, it was suggested that allowing
-anything (such as objects) could allow containers to offer a more advanced query API.
-
-An example given was to use the container as an object builder. The `$id` parameter would then be an
-object that would describe how to create an instance.
-
-The conclusion of the discussion was that this was beyond the scope of getting entries from a container without
-knowing how the container provided them, and it was more fit for a factory.
-
-## Contributors
-
-Are listed here all people that contributed in the discussions or votes, by alphabetical order:
-
-- [Amy Stephen](https://github.com/AmyStephen)
-- [David Négrier](https://github.com/moufmouf)
-- [Don Gilbert](https://github.com/dongilbert)
-- [Jason Judge](https://github.com/judgej)
-- [Jeremy Lindblom](https://github.com/jeremeamia)
-- [Marco Pivetta](https://github.com/Ocramius)
-- [Matthieu Napoli](https://github.com/mnapoli)
-- [Paul M. Jones](https://github.com/pmjones)
-- [Stephan Hochdörfer](https://github.com/shochdoerfer)
-- [Taylor Otwell](https://github.com/taylorotwell)
-
-## Relevant links
-
-- [`ContainerInterface.php`](https://github.com/container-interop/container-interop/blob/master/src/Interop/Container/ContainerInterface.php)
-- [List of all issues](https://github.com/container-interop/container-interop/issues?labels=ContainerInterface&milestone=&page=1&state=closed)
-- [Vote for the interface name](https://github.com/container-interop/container-interop/wiki/%231-interface-name:-Vote)
+++ /dev/null
-Container interface
-===================
-
-This document describes a common interface for dependency injection containers.
-
-The goal set by `ContainerInterface` is to standardize how frameworks and libraries make use of a
-container to obtain objects and parameters (called *entries* in the rest of this document).
-
-The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD",
-"SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be
-interpreted as described in [RFC 2119][].
-
-The word `implementor` in this document is to be interpreted as someone
-implementing the `ContainerInterface` in a depency injection-related library or framework.
-Users of dependency injections containers (DIC) are refered to as `user`.
-
-[RFC 2119]: http://tools.ietf.org/html/rfc2119
-
-1. Specification
------------------
-
-### 1.1 Basics
-
-- The `Interop\Container\ContainerInterface` exposes two methods : `get` and `has`.
-
-- `get` takes one mandatory parameter: an entry identifier. It MUST be a string.
- A call to `get` can return anything (a *mixed* value), or throws an exception if the identifier
- is not known to the container. Two successive calls to `get` with the same
- identifier SHOULD return the same value. However, depending on the `implementor`
- design and/or `user` configuration, different values might be returned, so
- `user` SHOULD NOT rely on getting the same value on 2 successive calls.
- While `ContainerInterface` only defines one mandatory parameter in `get()`, implementations
- MAY accept additional optional parameters.
-
-- `has` takes one unique parameter: an entry identifier. It MUST return `true`
- if an entry identifier is known to the container and `false` if it is not.
-
-### 1.2 Exceptions
-
-Exceptions directly thrown by the container MUST implement the
-[`Interop\Container\Exception\ContainerException`](../src/Interop/Container/Exception/ContainerException.php).
-
-A call to the `get` method with a non-existing id should throw a
-[`Interop\Container\Exception\NotFoundException`](../src/Interop/Container/Exception/NotFoundException.php).
-
-### 1.3 Additional features
-
-This section describes additional features that MAY be added to a container. Containers are not
-required to implement these features to respect the ContainerInterface.
-
-#### 1.3.1 Delegate lookup feature
-
-The goal of the *delegate lookup* feature is to allow several containers to share entries.
-Containers implementing this feature can perform dependency lookups in other containers.
-
-Containers implementing this feature will offer a greater lever of interoperability
-with other containers. Implementation of this feature is therefore RECOMMENDED.
-
-A container implementing this feature:
-
-- MUST implement the `ContainerInterface`
-- MUST provide a way to register a delegate container (using a constructor parameter, or a setter,
- or any possible way). The delegate container MUST implement the `ContainerInterface`.
-
-When a container is configured to use a delegate container for dependencies:
-
-- Calls to the `get` method should only return an entry if the entry is part of the container.
- If the entry is not part of the container, an exception should be thrown
- (as requested by the `ContainerInterface`).
-- Calls to the `has` method should only return `true` if the entry is part of the container.
- If the entry is not part of the container, `false` should be returned.
-- If the fetched entry has dependencies, **instead** of performing
- the dependency lookup in the container, the lookup is performed on the *delegate container*.
-
-Important! By default, the lookup SHOULD be performed on the delegate container **only**, not on the container itself.
-
-It is however allowed for containers to provide exception cases for special entries, and a way to lookup
-into the same container (or another container) instead of the delegate container.
-
-2. Package
-----------
-
-The interfaces and classes described as well as relevant exception are provided as part of the
-[container-interop/container-interop](https://packagist.org/packages/container-interop/container-interop) package.
-
-3. `Interop\Container\ContainerInterface`
------------------------------------------
-
-```php
-<?php
-namespace Interop\Container;
-
-use Interop\Container\Exception\ContainerException;
-use Interop\Container\Exception\NotFoundException;
-
-/**
- * Describes the interface of a container that exposes methods to read its entries.
- */
-interface ContainerInterface
-{
- /**
- * Finds an entry of the container by its identifier and returns it.
- *
- * @param string $id Identifier of the entry to look for.
- *
- * @throws NotFoundException No entry was found for this identifier.
- * @throws ContainerException Error while retrieving the entry.
- *
- * @return mixed Entry.
- */
- public function get($id);
-
- /**
- * Returns true if the container can return an entry for the given identifier.
- * Returns false otherwise.
- *
- * @param string $id Identifier of the entry to look for.
- *
- * @return boolean
- */
- public function has($id);
-}
-```
-
-4. `Interop\Container\Exception\ContainerException`
----------------------------------------------------
-
-```php
-<?php
-namespace Interop\Container\Exception;
-
-/**
- * Base interface representing a generic exception in a container.
- */
-interface ContainerException
-{
-}
-```
-
-5. `Interop\Container\Exception\NotFoundException`
----------------------------------------------------
-
-```php
-<?php
-namespace Interop\Container\Exception;
-
-/**
- * No entry was found in the container.
- */
-interface NotFoundException extends ContainerException
-{
-}
-```
+++ /dev/null
-Delegate lookup feature Meta Document
-=====================================
-
-1. Summary
-----------
-
-This document describes the *delegate lookup feature*.
-Containers are not required to implement this feature to respect the `ContainerInterface`.
-However, containers implementing this feature will offer a greater lever of interoperability
-with other containers, allowing multiple containers to share entries in the same application.
-Implementation of this feature is therefore recommanded.
-
-2. Why Bother?
---------------
-
-The [`ContainerInterface`](../src/Interop/Container/ContainerInterface.php) ([meta doc](ContainerInterface.md))
-standardizes how frameworks and libraries make use of a container to obtain objects and parameters.
-
-By standardizing such a behavior, frameworks and libraries relying on the `ContainerInterface`
-could work with any compatible container.
-That would allow end users to choose their own container based on their own preferences.
-
-The `ContainerInterface` is also enough if we want to have several containers side-by-side in the same
-application. For instance, this is what the [CompositeContainer](https://github.com/jeremeamia/acclimate-container/blob/master/src/CompositeContainer.php)
-class of [Acclimate](https://github.com/jeremeamia/acclimate-container) is designed for:
-
-![Side by side containers](images/side_by_side_containers.png)
-
-However, an instance in container 1 cannot reference an instance in container 2.
-
-It would be better if an instance of container 1 could reference an instance in container 2,
-and the opposite should be true.
-
-![Interoperating containers](images/interoperating_containers.png)
-
-In the sample above, entry 1 in container 1 is referencing entry 3 in container 2.
-
-3. Scope
---------
-
-### 3.1 Goals
-
-The goal of the *delegate lookup* feature is to allow several containers to share entries.
-
-4. Approaches
--------------
-
-### 4.1 Chosen Approach
-
-Containers implementing this feature can perform dependency lookups in other containers.
-
-A container implementing this feature:
-
-- must implement the `ContainerInterface`
-- must provide a way to register a *delegate container* (using a constructor parameter, or a setter, or any
-possible way). The *delegate container* must implement the `ContainerInterface`.
-
-When a *delegate container* is configured on a container:
-
-- Calls to the `get` method should only return an entry if the entry is part of the container.
-If the entry is not part of the container, an exception should be thrown (as required in the `ContainerInterface`).
-- Calls to the `has` method should only return *true* if the entry is part of the container.
-If the entry is not part of the container, *false* should be returned.
- - Finally, the important part: if the entry we are fetching has dependencies,
-**instead** of perfoming the dependency lookup in the container, the lookup is performed on the *delegate container*.
-
-Important! By default, the lookup should be performed on the delegate container **only**, not on the container itself.
-
-It is however allowed for containers to provide exception cases for special entries, and a way to lookup into
-the same container (or another container) instead of the delegate container.
-
-### 4.2 Typical usage
-
-The *delegate container* will usually be a composite container. A composite container is a container that
-contains several other containers. When performing a lookup on a composite container, the inner containers are
-queried until one container returns an entry.
-An inner container implementing the *delegate lookup feature* will return entries it contains, but if these
-entries have dependencies, the dependencies lookup calls will be performed on the composite container, giving
-a chance to all containers to answer.
-
-Interestingly enough, the order in which containers are added in the composite container matters. Indeed,
-the first containers to be added in the composite container can "override" the entries of containers with
-lower priority.
-
-![Containers priority](images/priority.png)
-
-In the example above, "container 2" contains a controller "myController" and the controller is referencing an
-"entityManager" entry. "Container 1" contains also an entry named "entityManager".
-Without the *delegate lookup* feature, when requesting the "myController" instance to container 2, it would take
-in charge the instanciation of both entries.
-
-However, using the *delegate lookup* feature, here is what happens when we ask the composite controller for the
-"myController" instance:
-
-- The composite controller asks container 1 if if contains the "myController" instance. The answer is no.
-- The composite controller asks container 2 if if contains the "myController" instance. The answer is yes.
-- The composite controller performs a `get` call on container 2 for the "myController" instance.
-- Container 2 sees that "myController" has a dependency on "entityManager".
-- Container 2 delegates the lookup of "entityManager" to the composite controller.
-- The composite controller asks container 1 if if contains the "entityManager" instance. The answer is yes.
-- The composite controller performs a `get` call on container 1 for the "entityManager" instance.
-
-In the end, we get a controller instanciated by container 2 that references an entityManager instanciated
-by container 1.
-
-### 4.3 Alternative: the fallback strategy
-
-The first proposed approach we tried was to perform all the lookups in the "local" container,
-and if a lookup fails in the container, to use the delegate container. In this scenario, the
-delegate container is used in "fallback" mode.
-
-This strategy has been described in @moufmouf blog post: http://mouf-php.com/container-interop-whats-next (solution 1).
-It was also discussed [here](https://github.com/container-interop/container-interop/pull/8#issuecomment-33570697) and
-[here](https://github.com/container-interop/container-interop/pull/20#issuecomment-56599631).
-
-Problems with this strategy:
-
-- Heavy problem regarding infinite loops
-- Unable to overload a container entry with the delegate container entry
-
-### 4.4 Alternative: force implementing an interface
-
-The first proposed approach was to develop a `ParentAwareContainerInterface` interface.
-It was proposed here: https://github.com/container-interop/container-interop/pull/8
-
-The interface would have had the behaviour of the delegate lookup feature but would have forced the addition of
-a `setParentContainter` method:
-
-```php
-interface ParentAwareContainerInterface extends ReadableContainerInterface {
- /**
- * Sets the parent container associated to that container. This container will call
- * the parent container to fetch dependencies.
- *
- * @param ContainerInterface $container
- */
- public function setParentContainer(ContainerInterface $container);
-}
-```
-
-The interface idea was first questioned by @Ocramius [here](https://github.com/container-interop/container-interop/pull/8#issuecomment-51721777).
-@Ocramius expressed the idea that an interface should not contain setters, otherwise, it is forcing implementation
-details on the class implementing the interface.
-Then @mnapoli made a proposal for a "convention" [here](https://github.com/container-interop/container-interop/pull/8#issuecomment-51841079),
-this idea was further discussed until all participants in the discussion agreed to remove the interface idea
-and replace it with a "standard" feature.
-
-**Pros:**
-
-If we had had an interface, we could have delegated the registration of the delegate/composite container to the
-the delegate/composite container itself.
-For instance:
-
-```php
-$containerA = new ContainerA();
-$containerB = new ContainerB();
-
-$compositeContainer = new CompositeContainer([$containerA, $containerB]);
-
-// The call to 'setParentContainer' is delegated to the CompositeContainer
-// It is not the responsibility of the user anymore.
-class CompositeContainer {
- ...
-
- public function __construct($containers) {
- foreach ($containers as $container) {
- if ($container instanceof ParentAwareContainerInterface) {
- $container->setParentContainer($this);
- }
- }
- ...
- }
-}
-
-```
-
-**Cons:**
-
-Cons have been extensively discussed [here](https://github.com/container-interop/container-interop/pull/8#issuecomment-51721777).
-Basically, forcing a setter into an interface is a bad idea. Setters are similar to constructor arguments,
-and it's a bad idea to standardize a constructor: how the delegate container is configured into a container is an implementation detail. This outweights the benefits of the interface.
-
-### 4.4 Alternative: no exception case for delegate lookups
-
-Originally, the proposed wording for delegate lookup calls was:
-
-> Important! The lookup MUST be performed on the delegate container **only**, not on the container itself.
-
-This was later replaced by:
-
-> Important! By default, the lookup SHOULD be performed on the delegate container **only**, not on the container itself.
->
-> It is however allowed for containers to provide exception cases for special entries, and a way to lookup
-> into the same container (or another container) instead of the delegate container.
-
-Exception cases have been allowed to avoid breaking dependencies with some services that must be provided
-by the container (on @njasm proposal). This was proposed here: https://github.com/container-interop/container-interop/pull/20#issuecomment-56597235
-
-### 4.5 Alternative: having one of the containers act as the composite container
-
-In real-life scenarios, we usually have a big framework (Symfony 2, Zend Framework 2, etc...) and we want to
-add another DI container to this container. Most of the time, the "big" framework will be responsible for
-creating the controller's instances, using it's own DI container. Until *container-interop* is fully adopted,
-the "big" framework will not be aware of the existence of a composite container that it should use instead
-of its own container.
-
-For this real-life use cases, @mnapoli and @moufmouf proposed to extend the "big" framework's DI container
-to make it act as a composite container.
-
-This has been discussed [here](https://github.com/container-interop/container-interop/pull/8#issuecomment-40367194)
-and [here](http://mouf-php.com/container-interop-whats-next#solution4).
-
-This was implemented in Symfony 2 using:
-
-- [interop.symfony.di](https://github.com/thecodingmachine/interop.symfony.di/tree/v0.1.0)
-- [framework interop](https://github.com/mnapoli/framework-interop/)
-
-This was implemented in Silex using:
-
-- [interop.silex.di](https://github.com/thecodingmachine/interop.silex.di)
-
-Having a container act as the composite container is not part of the delegate lookup standard because it is
-simply a temporary design pattern used to make existing frameworks that do not support yet ContainerInterop
-play nice with other DI containers.
-
-
-5. Implementations
-------------------
-
-The following projects already implement the delegate lookup feature:
-
-- [Mouf](http://mouf-php.com), through the [`setDelegateLookupContainer` method](https://github.com/thecodingmachine/mouf/blob/2.0/src/Mouf/MoufManager.php#L2120)
-- [PHP-DI](http://php-di.org/), through the [`$wrapperContainer` parameter of the constructor](https://github.com/mnapoli/PHP-DI/blob/master/src/DI/Container.php#L72)
-- [pimple-interop](https://github.com/moufmouf/pimple-interop), through the [`$container` parameter of the constructor](https://github.com/moufmouf/pimple-interop/blob/master/src/Interop/Container/Pimple/PimpleInterop.php#L62)
-
-6. People
----------
-
-Are listed here all people that contributed in the discussions, by alphabetical order:
-
-- [Alexandru Pătrănescu](https://github.com/drealecs)
-- [Ben Peachey](https://github.com/potherca)
-- [David Négrier](https://github.com/moufmouf)
-- [Jeremy Lindblom](https://github.com/jeremeamia)
-- [Marco Pivetta](https://github.com/Ocramius)
-- [Matthieu Napoli](https://github.com/mnapoli)
-- [Nelson J Morais](https://github.com/njasm)
-- [Phil Sturgeon](https://github.com/philsturgeon)
-- [Stephan Hochdörfer](https://github.com/shochdoerfer)
-
-7. Relevant Links
------------------
-
-_**Note:** Order descending chronologically._
-
-- [Pull request on the delegate lookup feature](https://github.com/container-interop/container-interop/pull/20)
-- [Pull request on the interface idea](https://github.com/container-interop/container-interop/pull/8)
-- [Original article exposing the delegate lookup idea along many others](http://mouf-php.com/container-interop-whats-next)
-
+++ /dev/null
-Delegate lookup feature
-=======================
-
-This document describes a standard for dependency injection containers.
-
-The goal set by the *delegate lookup* feature is to allow several containers to share entries.
-Containers implementing this feature can perform dependency lookups in other containers.
-
-Containers implementing this feature will offer a greater lever of interoperability
-with other containers. Implementation of this feature is therefore RECOMMENDED.
-
-The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD",
-"SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be
-interpreted as described in [RFC 2119][].
-
-The word `implementor` in this document is to be interpreted as someone
-implementing the delegate lookup feature in a dependency injection-related library or framework.
-Users of dependency injections containers (DIC) are refered to as `user`.
-
-[RFC 2119]: http://tools.ietf.org/html/rfc2119
-
-1. Vocabulary
--------------
-
-In a dependency injection container, the container is used to fetch entries.
-Entries can have dependencies on other entries. Usually, these other entries are fetched by the container.
-
-The *delegate lookup* feature is the ability for a container to fetch dependencies in
-another container. In the rest of the document, the word "container" will reference the container
-implemented by the implementor. The word "delegate container" will reference the container we are
-fetching the dependencies from.
-
-2. Specification
-----------------
-
-A container implementing the *delegate lookup* feature:
-
-- MUST implement the [`ContainerInterface`](ContainerInterface.md)
-- MUST provide a way to register a delegate container (using a constructor parameter, or a setter,
- or any possible way). The delegate container MUST implement the [`ContainerInterface`](ContainerInterface.md).
-
-When a container is configured to use a delegate container for dependencies:
-
-- Calls to the `get` method should only return an entry if the entry is part of the container.
- If the entry is not part of the container, an exception should be thrown
- (as requested by the [`ContainerInterface`](ContainerInterface.md)).
-- Calls to the `has` method should only return `true` if the entry is part of the container.
- If the entry is not part of the container, `false` should be returned.
-- If the fetched entry has dependencies, **instead** of performing
- the dependency lookup in the container, the lookup is performed on the *delegate container*.
-
-Important: By default, the dependency lookups SHOULD be performed on the delegate container **only**, not on the container itself.
-
-It is however allowed for containers to provide exception cases for special entries, and a way to lookup
-into the same container (or another container) instead of the delegate container.
-
-3. Package / Interface
-----------------------
-
-This feature is not tied to any code, interface or package.
+++ /dev/null
-<?php
-/**
- * @license http://www.opensource.org/licenses/mit-license.php MIT (see the LICENSE file)
- */
-
-namespace Interop\Container;
-
-use Interop\Container\Exception\ContainerException;
-use Interop\Container\Exception\NotFoundException;
-
-/**
- * Describes the interface of a container that exposes methods to read its entries.
- */
-interface ContainerInterface
-{
- /**
- * Finds an entry of the container by its identifier and returns it.
- *
- * @param string $id Identifier of the entry to look for.
- *
- * @throws NotFoundException No entry was found for this identifier.
- * @throws ContainerException Error while retrieving the entry.
- *
- * @return mixed Entry.
- */
- public function get($id);
-
- /**
- * Returns true if the container can return an entry for the given identifier.
- * Returns false otherwise.
- *
- * @param string $id Identifier of the entry to look for.
- *
- * @return boolean
- */
- public function has($id);
-}
+++ /dev/null
-<?php
-/**
- * @license http://www.opensource.org/licenses/mit-license.php MIT (see the LICENSE file)
- */
-
-namespace Interop\Container\Exception;
-
-/**
- * Base interface representing a generic exception in a container.
- */
-interface ContainerException
-{
-}
+++ /dev/null
-<?php
-/**
- * @license http://www.opensource.org/licenses/mit-license.php MIT (see the LICENSE file)
- */
-
-namespace Interop\Container\Exception;
-
-/**
- * No entry was found in the container.
- */
-interface NotFoundException extends ContainerException
-{
-}
+++ /dev/null
-# Contributing
-
-First of all, **thank you** for contributing!
-
-Here are a few rules to follow in order to ease code reviews and merging:
-
-- follow [PSR-1](http://www.php-fig.org/psr/1/) and [PSR-2](http://www.php-fig.org/psr/2/)
-- run the test suite
-- write (or update) unit tests when applicable
-- write documentation for new features
-- use [commit messages that make sense](http://tbaggery.com/2008/04/19/a-note-about-git-commit-messages.html)
-
-One may ask you to [squash your commits](http://gitready.com/advanced/2009/02/10/squashing-commits-with-rebase.html) too. This is used to "clean" your pull request before merging it (we don't want commits such as `fix tests`, `fix 2`, `fix 3`, etc.).
-
-When creating your pull request on GitHub, please write a description which gives the context and/or explains why you are creating it.
+++ /dev/null
-The MIT License (MIT)
-
-Copyright (c) Matthieu Napoli
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in
-all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-THE SOFTWARE.
+++ /dev/null
-# Invoker
-
-Generic and extensible callable invoker.
-
-[![Build Status](https://img.shields.io/travis/PHP-DI/Invoker.svg?style=flat-square)](https://travis-ci.org/PHP-DI/Invoker)
-[![Coverage Status](https://img.shields.io/coveralls/PHP-DI/Invoker/master.svg?style=flat-square)](https://coveralls.io/r/PHP-DI/Invoker?branch=master)
-[![Scrutinizer Code Quality](https://img.shields.io/scrutinizer/g/PHP-DI/Invoker.svg?style=flat-square)](https://scrutinizer-ci.com/g/PHP-DI/Invoker/?branch=master)
-[![Latest Version](https://img.shields.io/github/release/PHP-DI/invoker.svg?style=flat-square)](https://packagist.org/packages/PHP-DI/invoker)
-
-## Why?
-
-Who doesn't need an over-engineered `call_user_func()`?
-
-### Named parameters
-
-Does this [Silex](http://silex.sensiolabs.org) example look familiar:
-
-```php
-$app->get('/project/{project}/issue/{issue}', function ($project, $issue) {
- // ...
-});
-```
-
-Or this command defined with [Silly](https://github.com/mnapoli/silly#usage):
-
-```php
-$app->command('greet [name] [--yell]', function ($name, $yell) {
- // ...
-});
-```
-
-Same pattern in [Slim](http://www.slimframework.com):
-
-```php
-$app->get('/hello/:name', function ($name) {
- // ...
-});
-```
-
-You get the point. These frameworks invoke the controller/command/handler using something akin to named parameters: whatever the order of the parameters, they are matched by their name.
-
-**This library allows to invoke callables with named parameters in a generic and extensible way.**
-
-### Dependency injection
-
-Anyone familiar with AngularJS is familiar with how dependency injection is performed:
-
-```js
-angular.controller('MyController', ['dep1', 'dep2', function(dep1, dep2) {
- // ...
-}]);
-```
-
-In PHP we find this pattern again in some frameworks and DI containers with partial to full support. For example in Silex you can type-hint the application to get it injected, but it only works with `Silex\Application`:
-
-```php
-$app->get('/hello/{name}', function (Silex\Application $app, $name) {
- // ...
-});
-```
-
-In Silly, it only works with `OutputInterface` to inject the application output:
-
-```php
-$app->command('greet [name]', function ($name, OutputInterface $output) {
- // ...
-});
-```
-
-[PHP-DI](http://php-di.org/doc/container.html) provides a way to invoke a callable and resolve all dependencies from the container using type-hints:
-
-```php
-$container->call(function (Logger $logger, EntityManager $em) {
- // ...
-});
-```
-
-**This library provides clear extension points to let frameworks implement any kind of dependency injection support they want.**
-
-### TL/DR
-
-In short, this library is meant to be a base building block for calling a function with named parameters and/or dependency injection.
-
-## Installation
-
-```sh
-$ composer require PHP-DI/invoker
-```
-
-## Usage
-
-### Default behavior
-
-By default the `Invoker` can call using named parameters:
-
-```php
-$invoker = new Invoker\Invoker;
-
-$invoker->call(function () {
- echo 'Hello world!';
-});
-
-// Simple parameter array
-$invoker->call(function ($name) {
- echo 'Hello ' . $name;
-}, ['John']);
-
-// Named parameters
-$invoker->call(function ($name) {
- echo 'Hello ' . $name;
-}, [
- 'name' => 'John'
-]);
-
-// Use the default value
-$invoker->call(function ($name = 'world') {
- echo 'Hello ' . $name;
-});
-
-// Invoke any PHP callable
-$invoker->call(['MyClass', 'myStaticMethod']);
-
-// Using Class::method syntax
-$invoker->call('MyClass::myStaticMethod');
-```
-
-Dependency injection in parameters is supported but needs to be configured with your container. Read on or jump to [*Built-in support for dependency injection*](#built-in-support-for-dependency-injection) if you are impatient.
-
-Additionally, callables can also be resolved from your container. Read on or jump to [*Resolving callables from a container*](#resolving-callables-from-a-container) if you are impatient.
-
-### Parameter resolvers
-
-Extending the behavior of the `Invoker` is easy and is done by implementing a [`ParameterResolver`](https://github.com/PHP-DI/Invoker/blob/master/src/ParameterResolver/ParameterResolver.php).
-
-This is explained in details the [Parameter resolvers documentation](doc/parameter-resolvers.md).
-
-#### Built-in support for dependency injection
-
-Rather than have you re-implement support for dependency injection with different containers every time, this package ships with 2 optional resolvers:
-
-- [`TypeHintContainerResolver`](https://github.com/PHP-DI/Invoker/blob/master/src/ParameterResolver/Container/TypeHintContainerResolver.php)
-
- This resolver will inject container entries by searching for the class name using the type-hint:
-
- ```php
- $invoker->call(function (Psr\Logger\LoggerInterface $logger) {
- // ...
- });
- ```
-
- In this example it will `->get('Psr\Logger\LoggerInterface')` from the container and inject it.
-
- This resolver is only useful if you store objects in your container using the class (or interface) name. Silex or Symfony for example store services under a custom name (e.g. `twig`, `db`, etc.) instead of the class name: in that case use the resolver shown below.
-
-- [`ParameterNameContainerResolver`](https://github.com/PHP-DI/Invoker/blob/master/src/ParameterResolver/Container/ParameterNameContainerResolver.php)
-
- This resolver will inject container entries by searching for the name of the parameter:
-
- ```php
- $invoker->call(function ($twig) {
- // ...
- });
- ```
-
- In this example it will `->get('twig')` from the container and inject it.
-
-These resolvers can work with any dependency injection container compliant with [container-interop](https://github.com/container-interop/container-interop). If you container is not compliant you can use the [Acclimate](https://github.com/jeremeamia/acclimate-container) package.
-
-Setting up those resolvers is simple:
-
-```php
-// $container must be an instance of Interop\Container\ContainerInterface
-$container = ...
-
-$containerResolver = new TypeHintContainerResolver($container);
-// or
-$containerResolver = new ParameterNameContainerResolver($container);
-
-$invoker = new Invoker\Invoker;
-// Register it before all the other parameter resolvers
-$invoker->getParameterResolver()->prependResolver($containerResolver);
-```
-
-You can also register both resolvers at the same time if you wish by prepending both. Implementing support for more tricky things is easy and up to you!
-
-### Resolving callables from a container
-
-The `Invoker` can be wired to your DI container to resolve the callables.
-
-For example with an invokable class:
-
-```php
-class MyHandler
-{
- public function __invoke()
- {
- // ...
- }
-}
-
-// By default this doesn't work: an instance of the class should be provided
-$invoker->call('MyHandler');
-
-// If we set up the container to use
-$invoker = new Invoker\Invoker(null, $container);
-// Now 'MyHandler' is resolved using the container!
-$invoker->call('MyHandler');
-```
-
-The same works for a class method:
-
-```php
-class WelcomeController
-{
- public function home()
- {
- // ...
- }
-}
-
-// By default this doesn't work: home() is not a static method
-$invoker->call(['WelcomeController', 'home']);
-
-// If we set up the container to use
-$invoker = new Invoker\Invoker(null, $container);
-// Now 'WelcomeController' is resolved using the container!
-$invoker->call(['WelcomeController', 'home']);
-// Alternatively we can use the Class::method syntax
-$invoker->call('WelcomeController::home');
-```
-
-That feature can be used as the base building block for a framework's dispatcher.
-
-Again, any [container-interop](https://github.com/container-interop/container-interop) compliant container can be provided, and [Acclimate](https://github.com/jeremeamia/acclimate-container) can be used for incompatible containers.
+++ /dev/null
-{
- "name": "php-di/invoker",
- "description": "Generic and extensible callable invoker",
- "keywords": ["invoker", "dependency-injection", "dependency", "injection", "callable", "invoke"],
- "homepage": "https://github.com/PHP-DI/Invoker",
- "license": "MIT",
- "type": "library",
- "autoload": {
- "psr-4": {
- "Invoker\\": "src/"
- }
- },
- "autoload-dev": {
- "psr-4": {
- "Invoker\\Test\\": "tests/"
- }
- },
- "require": {
- "container-interop/container-interop": "~1.1"
- },
- "require-dev": {
- "phpunit/phpunit": "~4.5",
- "athletic/athletic": "~0.1.8"
- }
-}
+++ /dev/null
-# Parameter resolvers
-
-Extending the behavior of the `Invoker` is easy and is done by implementing a [`ParameterResolver`](https://github.com/PHP-DI/Invoker/blob/master/src/ParameterResolver/ParameterResolver.php):
-
-```php
-interface ParameterResolver
-{
- public function getParameters(
- ReflectionFunctionAbstract $reflection,
- array $providedParameters,
- array $resolvedParameters
- );
-}
-```
-
-- `$providedParameters` contains the parameters provided by the user when calling `$invoker->call($callable, $parameters)`
-- `$resolvedParameters` contains parameters that have already been resolved by other parameter resolvers
-
-An `Invoker` can chain multiple parameter resolvers to mix behaviors, e.g. you can mix "named parameters" support with "dependency injection" support. This is why a `ParameterResolver` should skip parameters that are already resolved in `$resolvedParameters`.
-
-Here is an implementation example for dumb dependency injection that creates a new instance of the classes type-hinted:
-
-```php
-class MyParameterResolver implements ParameterResolver
-{
- public function getParameters(
- ReflectionFunctionAbstract $reflection,
- array $providedParameters,
- array $resolvedParameters
- ) {
- foreach ($reflection->getParameters() as $index => $parameter) {
- if (array_key_exists($index, $resolvedParameters)) {
- // Skip already resolved parameters
- continue;
- }
-
- $class = $parameter->getClass();
-
- if ($class) {
- $resolvedParameters[$index] = $class->newInstance();
- }
- }
-
- return $resolvedParameters;
- }
-}
-```
-
-To use it:
-
-```php
-$invoker = new Invoker\Invoker(new MyParameterResolver);
-
-$invoker->call(function (ArticleManager $articleManager) {
- $articleManager->publishArticle('Hello world', 'This is the article content.');
-});
-```
-
-A new instance of `ArticleManager` will be created by our parameter resolver.
-
-## Chaining parameter resolvers
-
-The fun starts to happen when we want to add support for many things:
-
-- named parameters
-- dependency injection for type-hinted parameters
-- ...
-
-This is where we should use the [`ResolverChain`](https://github.com/PHP-DI/Invoker/blob/master/src/ParameterResolver/ResolverChain.php). This resolver implements the [Chain of responsibility](http://en.wikipedia.org/wiki/Chain-of-responsibility_pattern) design pattern.
-
-For example the default chain is:
-
-```php
-$parameterResolver = new ResolverChain([
- new NumericArrayResolver,
- new AssociativeArrayResolver,
- new DefaultValueResolver,
-]);
-```
-
-It allows to support even the weirdest use cases like:
-
-```php
-$parameters = [];
-
-// First parameter will receive "Welcome"
-$parameters[] = 'Welcome';
-
-// Parameter named "content" will receive "Hello world!"
-$parameters['content'] = 'Hello world!';
-
-// $published is not defined so it will use its default value
-$invoker->call(function ($title, $content, $published = true) {
- // ...
-}, $parameters);
-```
-
-We can put our custom parameter resolver in the list and created a super-duper invoker that also supports basic dependency injection:
-
-```php
-$parameterResolver = new ResolverChain([
- new MyParameterResolver, // Our resolver is at the top for highest priority
- new NumericArrayResolver,
- new AssociativeArrayResolver,
- new DefaultValueResolver,
-]);
-
-$invoker = new Invoker\Invoker($parameterResolver);
-```
+++ /dev/null
-<?php
-
-namespace Invoker;
-
-use Interop\Container\ContainerInterface;
-use Invoker\Exception\NotCallableException;
-
-/**
- * Resolves a callable from a container.
- *
- * @author Matthieu Napoli <matthieu@mnapoli.fr>
- */
-class CallableResolver
-{
- /**
- * @var ContainerInterface
- */
- private $container;
-
- public function __construct(ContainerInterface $container)
- {
- $this->container = $container;
- }
-
- /**
- * Resolve the given callable into a real PHP callable.
- *
- * @param callable|string|array $callable
- *
- * @return callable Real PHP callable.
- *
- * @throws NotCallableException
- */
- public function resolve($callable)
- {
- if (is_string($callable) && strpos($callable, '::') !== false) {
- $callable = explode('::', $callable, 2);
- }
-
- $callable = $this->resolveFromContainer($callable);
-
- if (! is_callable($callable)) {
- throw new NotCallableException(sprintf(
- '%s is not a callable',
- is_object($callable) ? 'Instance of ' . get_class($callable) : var_export($callable, true)
- ));
- }
-
- return $callable;
- }
-
- /**
- * @param callable|string|array $callable
- * @return callable
- * @throws NotCallableException
- */
- private function resolveFromContainer($callable)
- {
- // Shortcut for a very common use case
- if ($callable instanceof \Closure) {
- return $callable;
- }
-
- $isStaticCallToNonStaticMethod = false;
-
- // If it's already a callable there is nothing to do
- if (is_callable($callable)) {
- $isStaticCallToNonStaticMethod = $this->isStaticCallToNonStaticMethod($callable);
- if (! $isStaticCallToNonStaticMethod) {
- return $callable;
- }
- }
-
- // The callable is a container entry name
- if (is_string($callable)) {
- if ($this->container->has($callable)) {
- return $this->container->get($callable);
- } else {
- throw new NotCallableException(sprintf(
- '"%s" is neither a callable nor a valid container entry',
- $callable
- ));
- }
- }
-
- // The callable is an array whose first item is a container entry name
- // e.g. ['some-container-entry', 'methodToCall']
- if (is_array($callable) && is_string($callable[0])) {
- if ($this->container->has($callable[0])) {
- // Replace the container entry name by the actual object
- $callable[0] = $this->container->get($callable[0]);
- return $callable;
- } elseif ($isStaticCallToNonStaticMethod) {
- throw new NotCallableException(sprintf(
- 'Cannot call %s::%s() because %s() is not a static method and "%s" is not a container entry',
- $callable[0],
- $callable[1],
- $callable[1],
- $callable[0]
- ));
- } else {
- throw new NotCallableException(sprintf(
- 'Cannot call %s on %s because it is not a class nor a valid container entry',
- $callable[1],
- $callable[0]
- ));
- }
- }
-
- // Unrecognized stuff, we let it fail later
- return $callable;
- }
-
- /**
- * Check if the callable represents a static call to a non-static method.
- *
- * @param mixed $callable
- * @return bool
- */
- private function isStaticCallToNonStaticMethod($callable)
- {
- if (is_array($callable) && is_string($callable[0])) {
- list($class, $method) = $callable;
- $reflection = new \ReflectionMethod($class, $method);
-
- return ! $reflection->isStatic();
- }
-
- return false;
- }
-}
+++ /dev/null
-<?php
-
-namespace Invoker\Exception;
-
-/**
- * Impossible to invoke the callable.
- *
- * @author Matthieu Napoli <matthieu@mnapoli.fr>
- */
-class InvocationException extends \Exception
-{
-}
+++ /dev/null
-<?php
-
-namespace Invoker\Exception;
-
-/**
- * The given callable is not actually callable.
- *
- * @author Matthieu Napoli <matthieu@mnapoli.fr>
- */
-class NotCallableException extends InvocationException
-{
-}
+++ /dev/null
-<?php
-
-namespace Invoker\Exception;
-
-/**
- * Not enough parameters could be resolved to invoke the callable.
- *
- * @author Matthieu Napoli <matthieu@mnapoli.fr>
- */
-class NotEnoughParametersException extends InvocationException
-{
-}
+++ /dev/null
-<?php
-
-namespace Invoker;
-
-use Interop\Container\ContainerInterface;
-use Invoker\Exception\NotCallableException;
-use Invoker\Exception\NotEnoughParametersException;
-use Invoker\ParameterResolver\AssociativeArrayResolver;
-use Invoker\ParameterResolver\DefaultValueResolver;
-use Invoker\ParameterResolver\NumericArrayResolver;
-use Invoker\ParameterResolver\ParameterResolver;
-use Invoker\ParameterResolver\ResolverChain;
-use Invoker\Reflection\CallableReflection;
-
-/**
- * Invoke a callable.
- *
- * @author Matthieu Napoli <matthieu@mnapoli.fr>
- */
-class Invoker implements InvokerInterface
-{
- /**
- * @var CallableResolver|null
- */
- private $callableResolver;
-
- /**
- * @var ParameterResolver
- */
- private $parameterResolver;
-
- /**
- * @var ContainerInterface|null
- */
- private $container;
-
- public function __construct(ParameterResolver $parameterResolver = null, ContainerInterface $container = null)
- {
- $this->parameterResolver = $parameterResolver ?: $this->createParameterResolver();
- $this->container = $container;
-
- if ($container) {
- $this->callableResolver = new CallableResolver($container);
- }
- }
-
- /**
- * {@inheritdoc}
- */
- public function call($callable, array $parameters = array())
- {
- if ($this->callableResolver) {
- $callable = $this->callableResolver->resolve($callable);
- }
-
- if (! is_callable($callable)) {
- throw new NotCallableException(sprintf(
- '%s is not a callable',
- is_object($callable) ? 'Instance of ' . get_class($callable) : var_export($callable, true)
- ));
- }
-
- $callableReflection = CallableReflection::create($callable);
-
- $args = $this->parameterResolver->getParameters($callableReflection, $parameters, array());
-
- // Sort by array key because call_user_func_array ignores numeric keys
- ksort($args);
-
- // Check all parameters are resolved
- $diff = array_diff_key($callableReflection->getParameters(), $args);
- if (! empty($diff)) {
- /** @var \ReflectionParameter $parameter */
- $parameter = reset($diff);
- throw new NotEnoughParametersException(sprintf(
- 'Unable to invoke the callable because no value was given for parameter %d ($%s)',
- $parameter->getPosition() + 1,
- $parameter->name
- ));
- }
-
- return call_user_func_array($callable, $args);
- }
-
- /**
- * Create the default parameter resolver.
- *
- * @return ParameterResolver
- */
- private function createParameterResolver()
- {
- return new ResolverChain(array(
- new NumericArrayResolver,
- new AssociativeArrayResolver,
- new DefaultValueResolver,
- ));
- }
-
- /**
- * @return ParameterResolver By default it's a ResolverChain
- */
- public function getParameterResolver()
- {
- return $this->parameterResolver;
- }
-
- /**
- * @return ContainerInterface|null
- */
- public function getContainer()
- {
- return $this->container;
- }
-
- /**
- * @return CallableResolver|null Returns null if no container was given in the constructor.
- */
- public function getCallableResolver()
- {
- return $this->callableResolver;
- }
-}
+++ /dev/null
-<?php
-
-namespace Invoker;
-
-use Invoker\Exception\InvocationException;
-use Invoker\Exception\NotCallableException;
-use Invoker\Exception\NotEnoughParametersException;
-
-/**
- * Invoke a callable.
- *
- * @author Matthieu Napoli <matthieu@mnapoli.fr>
- */
-interface InvokerInterface
-{
- /**
- * Call the given function using the given parameters.
- *
- * @param callable $callable Function to call.
- * @param array $parameters Parameters to use.
- *
- * @return mixed Result of the function.
- *
- * @throws InvocationException Base exception class for all the sub-exceptions below.
- * @throws NotCallableException
- * @throws NotEnoughParametersException
- */
- public function call($callable, array $parameters = array());
-}
+++ /dev/null
-<?php
-
-namespace Invoker\ParameterResolver;
-
-use ReflectionFunctionAbstract;
-
-/**
- * Tries to map an associative array (string-indexed) to the parameter names.
- *
- * E.g. `->call($callable, ['foo' => 'bar'])` will inject the string `'bar'`
- * in the parameter named `$foo`.
- *
- * Parameters that are not indexed by a string are ignored.
- *
- * @author Matthieu Napoli <matthieu@mnapoli.fr>
- */
-class AssociativeArrayResolver implements ParameterResolver
-{
- public function getParameters(
- ReflectionFunctionAbstract $reflection,
- array $providedParameters,
- array $resolvedParameters
- ) {
- $parameters = $reflection->getParameters();
-
- // Skip parameters already resolved
- if (! empty($resolvedParameters)) {
- $parameters = array_diff_key($parameters, $resolvedParameters);
- }
-
- foreach ($parameters as $index => $parameter) {
- if (array_key_exists($parameter->name, $providedParameters)) {
- $resolvedParameters[$index] = $providedParameters[$parameter->name];
- }
- }
-
- return $resolvedParameters;
- }
-}
+++ /dev/null
-<?php
-
-namespace Invoker\ParameterResolver\Container;
-
-use Interop\Container\ContainerInterface;
-use Invoker\ParameterResolver\ParameterResolver;
-use ReflectionFunctionAbstract;
-
-/**
- * Inject entries from a DI container using the parameter names.
- *
- * @author Matthieu Napoli <matthieu@mnapoli.fr>
- */
-class ParameterNameContainerResolver implements ParameterResolver
-{
- /**
- * @var ContainerInterface
- */
- private $container;
-
- /**
- * @param ContainerInterface $container The container to get entries from.
- */
- public function __construct(ContainerInterface $container)
- {
- $this->container = $container;
- }
-
- public function getParameters(
- ReflectionFunctionAbstract $reflection,
- array $providedParameters,
- array $resolvedParameters
- ) {
- $parameters = $reflection->getParameters();
-
- // Skip parameters already resolved
- if (! empty($resolvedParameters)) {
- $parameters = array_diff_key($parameters, $resolvedParameters);
- }
-
- foreach ($parameters as $index => $parameter) {
- $name = $parameter->name;
-
- if ($name && $this->container->has($name)) {
- $resolvedParameters[$index] = $this->container->get($name);
- }
- }
-
- return $resolvedParameters;
- }
-}
+++ /dev/null
-<?php
-
-namespace Invoker\ParameterResolver\Container;
-
-use Interop\Container\ContainerInterface;
-use Invoker\ParameterResolver\ParameterResolver;
-use ReflectionFunctionAbstract;
-
-/**
- * Inject entries from a DI container using the type-hints.
- *
- * @author Matthieu Napoli <matthieu@mnapoli.fr>
- */
-class TypeHintContainerResolver implements ParameterResolver
-{
- /**
- * @var ContainerInterface
- */
- private $container;
-
- /**
- * @param ContainerInterface $container The container to get entries from.
- */
- public function __construct(ContainerInterface $container)
- {
- $this->container = $container;
- }
-
- public function getParameters(
- ReflectionFunctionAbstract $reflection,
- array $providedParameters,
- array $resolvedParameters
- ) {
- $parameters = $reflection->getParameters();
-
- // Skip parameters already resolved
- if (! empty($resolvedParameters)) {
- $parameters = array_diff_key($parameters, $resolvedParameters);
- }
-
- foreach ($parameters as $index => $parameter) {
- $parameterClass = $parameter->getClass();
-
- if ($parameterClass && $this->container->has($parameterClass->name)) {
- $resolvedParameters[$index] = $this->container->get($parameterClass->name);
- }
- }
-
- return $resolvedParameters;
- }
-}
+++ /dev/null
-<?php
-
-namespace Invoker\ParameterResolver;
-
-use ReflectionException;
-use ReflectionFunctionAbstract;
-
-/**
- * Finds the default value for a parameter, *if it exists*.
- *
- * @author Matthieu Napoli <matthieu@mnapoli.fr>
- */
-class DefaultValueResolver implements ParameterResolver
-{
- public function getParameters(
- ReflectionFunctionAbstract $reflection,
- array $providedParameters,
- array $resolvedParameters
- ) {
- $parameters = $reflection->getParameters();
-
- // Skip parameters already resolved
- if (! empty($resolvedParameters)) {
- $parameters = array_diff_key($parameters, $resolvedParameters);
- }
-
- foreach ($parameters as $index => $parameter) {
- /** @var \ReflectionParameter $parameter */
- if ($parameter->isOptional()) {
- try {
- $resolvedParameters[$index] = $parameter->getDefaultValue();
- } catch (ReflectionException $e) {
- // Can't get default values from PHP internal classes and functions
- }
- }
- }
-
- return $resolvedParameters;
- }
-}
+++ /dev/null
-<?php
-
-namespace Invoker\ParameterResolver;
-
-use ReflectionFunctionAbstract;
-
-/**
- * Simply returns all the values of the $providedParameters array that are
- * indexed by the parameter position (i.e. a number).
- *
- * E.g. `->call($callable, ['foo', 'bar'])` will simply resolve the parameters
- * to `['foo', 'bar']`.
- *
- * Parameters that are not indexed by a number (i.e. parameter position)
- * will be ignored.
- *
- * @author Matthieu Napoli <matthieu@mnapoli.fr>
- */
-class NumericArrayResolver implements ParameterResolver
-{
- public function getParameters(
- ReflectionFunctionAbstract $reflection,
- array $providedParameters,
- array $resolvedParameters
- ) {
- // Skip parameters already resolved
- if (! empty($resolvedParameters)) {
- $providedParameters = array_diff_key($providedParameters, $resolvedParameters);
- }
-
- foreach ($providedParameters as $key => $value) {
- if (is_int($key)) {
- $resolvedParameters[$key] = $value;
- }
- }
-
- return $resolvedParameters;
- }
-}
+++ /dev/null
-<?php
-
-namespace Invoker\ParameterResolver;
-
-use ReflectionFunctionAbstract;
-
-/**
- * Resolves the parameters to use to call the callable.
- *
- * @author Matthieu Napoli <matthieu@mnapoli.fr>
- */
-interface ParameterResolver
-{
- /**
- * Resolves the parameters to use to call the callable.
- *
- * `$resolvedParameters` contains parameters that have already been resolved.
- *
- * Each ParameterResolver must resolve parameters that are not already
- * in `$resolvedParameters`. That allows to chain multiple ParameterResolver.
- *
- * @param ReflectionFunctionAbstract $reflection Reflection object for the callable.
- * @param array $providedParameters Parameters provided by the caller.
- * @param array $resolvedParameters Parameters resolved (indexed by parameter position).
- *
- * @return array
- */
- public function getParameters(
- ReflectionFunctionAbstract $reflection,
- array $providedParameters,
- array $resolvedParameters
- );
-}
+++ /dev/null
-<?php
-
-namespace Invoker\ParameterResolver;
-
-use ReflectionFunctionAbstract;
-
-/**
- * Dispatches the call to other resolvers until all parameters are resolved.
- *
- * Chain of responsibility pattern.
- *
- * @author Matthieu Napoli <matthieu@mnapoli.fr>
- */
-class ResolverChain implements ParameterResolver
-{
- /**
- * @var ParameterResolver[]
- */
- private $resolvers = array();
-
- public function __construct(array $resolvers = array())
- {
- $this->resolvers = $resolvers;
- }
-
- public function getParameters(
- ReflectionFunctionAbstract $reflection,
- array $providedParameters,
- array $resolvedParameters
- ) {
- $reflectionParameters = $reflection->getParameters();
-
- foreach ($this->resolvers as $resolver) {
- $resolvedParameters = $resolver->getParameters(
- $reflection,
- $providedParameters,
- $resolvedParameters
- );
-
- $diff = array_diff_key($reflectionParameters, $resolvedParameters);
- if (empty($diff)) {
- // Stop traversing: all parameters are resolved
- return $resolvedParameters;
- }
- }
-
- return $resolvedParameters;
- }
-
- /**
- * Push a parameter resolver after the ones already registered.
- *
- * @param ParameterResolver $resolver
- */
- public function appendResolver(ParameterResolver $resolver)
- {
- $this->resolvers[] = $resolver;
- }
-
- /**
- * Insert a parameter resolver before the ones already registered.
- *
- * @param ParameterResolver $resolver
- */
- public function prependResolver(ParameterResolver $resolver)
- {
- array_unshift($this->resolvers, $resolver);
- }
-}
+++ /dev/null
-<?php
-
-namespace Invoker\Reflection;
-
-use Invoker\Exception\NotCallableException;
-
-/**
- * Create a reflection object from a callable.
- *
- * @author Matthieu Napoli <matthieu@mnapoli.fr>
- */
-class CallableReflection
-{
- /**
- * @param callable $callable
- *
- * @return \ReflectionFunctionAbstract
- *
- * @throws NotCallableException
- *
- * TODO Use the `callable` type-hint once support for PHP 5.4 and up.
- */
- public static function create($callable)
- {
- // Closure
- if ($callable instanceof \Closure) {
- return new \ReflectionFunction($callable);
- }
-
- // Array callable
- if (is_array($callable)) {
- list($class, $method) = $callable;
-
- return new \ReflectionMethod($class, $method);
- }
-
- // Callable object (i.e. implementing __invoke())
- if (is_object($callable) && method_exists($callable, '__invoke')) {
- return new \ReflectionMethod($callable, '__invoke');
- }
-
- // Callable class (i.e. implementing __invoke())
- if (is_string($callable) && class_exists($callable) && method_exists($callable, '__invoke')) {
- return new \ReflectionMethod($callable, '__invoke');
- }
-
- // Standard function
- if (is_string($callable) && function_exists($callable)) {
- return new \ReflectionFunction($callable);
- }
-
- throw new NotCallableException(sprintf(
- '%s is not a callable',
- is_string($callable) ? $callable : 'Instance of ' . get_class($callable)
- ));
- }
-}
+++ /dev/null
-coverage_clover: clover.xml
-json_path: coveralls-upload.json
+++ /dev/null
-# .gitattributes
-tests/ export-ignore
-website/ export-ignore
-doc/ export-ignore
-news/ export-ignore
-
-# Auto detect text files and perform LF normalization
-* text=auto
+++ /dev/null
-/.idea/
-/vendor/
-/composer.phar
-/composer.lock
-/theme/
-/.couscous/
-/website/bower_components/
-/website/css/all.min.css
-/logo/
+++ /dev/null
-language: php
-
-php:
- - 5.4
- - 5.5
- - 5.6
- - 7.0
- - hhvm
-
-matrix:
- include:
- - php: 5.4
- env: dependencies=lowest
-
-before_script:
- - composer self-update
- - if [[ $(phpenv version-name) == '5.6' ]]; then composer require satooshi/php-coveralls:dev-master -n ; fi
- - if [[ $(phpenv version-name) != '5.6' ]]; then composer install -n ; fi
- - if [ "$dependencies" = "lowest" ]; then composer update --prefer-lowest --prefer-stable -n; fi;
-
-script:
- - if [[ $(phpenv version-name) == '5.6' ]]; then phpunit --coverage-clover clover.xml ; fi
- - if [[ $(phpenv version-name) != '5.6' ]]; then phpunit ; fi
-
-after_script:
- - if [[ $(phpenv version-name) == '5.6' ]]; then php vendor/bin/coveralls -v ; fi
+++ /dev/null
----
-layout: 404
----
+++ /dev/null
-# Contributing
-
-[![Build Status](https://travis-ci.org/PHP-DI/PHP-DI.png?branch=master)](https://travis-ci.org/PHP-DI/PHP-DI) [![Coverage Status](https://coveralls.io/repos/PHP-DI/PHP-DI/badge.png?branch=master)](https://coveralls.io/r/PHP-DI/PHP-DI?branch=master)
-
-PHP-DI is licensed under the MIT License.
-
-
-## Set up
-
-* Check out the sources using git or download them
-
-```bash
-$ git clone https://github.com/PHP-DI/PHP-DI.git
-```
-
-* Install the libraries using composer:
-
-```bash
-$ curl -s http://getcomposer.org/installer | php
-$ php composer.phar install
-```
-
-If you are running Windows or are having trouble, read [the official documentation](http://getcomposer.org/doc/00-intro.md#installation).
-
-
-## Run the tests
-
-The tests are run with [PHPUnit](http://www.phpunit.de/manual/current/en/installation.html):
-
-```bash
-$ phpunit
-```
-
-
-## Learning the internals
-
-Read the [How it works](doc/how-it-works.md) documentation.
-
-
-## What to do?
-
-- Add tests: pick up uncovered situations in the [code coverage report](https://coveralls.io/r/PHP-DI/PHP-DI)
-- Resolve issues: [issue list](https://github.com/PHP-DI/PHP-DI/issues)
-- Improve the documentation
-- …
-
-
-## Coding style
-
-The code follows PSR0, PSR1 and [PSR2](https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-2-coding-style-guide.md).
-
-Also, do not hesitate to add your name to the author list of a class in the docblock if you improve it.
+++ /dev/null
-PHP-DI - PHP Dependency Injection
-
-Copyright (C) Matthieu Napoli
-
-Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
-associated documentation files (the "Software"), to deal in the Software without restriction,
-including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense,
-and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so,
-subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all copies or substantial
-portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT
-NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
-IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
-WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
-SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+++ /dev/null
----
-layout: home
----
-
-PHP-DI is a Dependency Injection Container made for humans.
-
-[![Build Status](https://img.shields.io/travis/PHP-DI/PHP-DI.svg?style=flat-square)](https://travis-ci.org/PHP-DI/PHP-DI)
-[![HHVM Status](https://img.shields.io/hhvm/php-di/php-di.svg?style=flat-square)](http://hhvm.h4cc.de/package/php-di/php-di)
-[![Coverage Status](https://img.shields.io/coveralls/PHP-DI/PHP-DI/master.svg?style=flat-square)](https://coveralls.io/r/PHP-DI/PHP-DI?branch=master)
-[![Scrutinizer Code Quality](https://img.shields.io/scrutinizer/g/PHP-DI/PHP-DI.svg?style=flat-square)](https://scrutinizer-ci.com/g/PHP-DI/PHP-DI/?branch=master)
-[![Latest Version](https://img.shields.io/github/release/PHP-DI/PHP-DI.svg?style=flat-square)](https://packagist.org/packages/php-di/php-di)
-[![Total Downloads](https://img.shields.io/packagist/dt/mnapoli/PHP-DI.svg?style=flat-square)](https://packagist.org/packages/mnapoli/php-di)
-
-[![Average time to resolve an issue](http://isitmaintained.com/badge/resolution/PHP-DI/PHP-DI.svg)](http://isitmaintained.com/project/PHP-DI/PHP-DI "Average time to resolve an issue")
-[![Percentage of issues still open](http://isitmaintained.com/badge/open/PHP-DI/PHP-DI.svg)](http://isitmaintained.com/project/PHP-DI/PHP-DI "Percentage of issues still open")
-
-It is meant to be practical, powerful, and framework-agnostic.
-
-Read more on the website: **[php-di.org](http://php-di.org)**
-
-Join us in the Gitter chat room: [![Gitter chat](https://badges.gitter.im/PHP-DI/PHP-DI.png)](https://gitter.im/PHP-DI/PHP-DI)
+++ /dev/null
-# Change log
-
-## 5.1
-
-Read the [news entry](news/16-php-di-5-1-released.md).
-
-Improvements:
-
-- [Zend Framework 2 integration](https://github.com/PHP-DI/ZF2-Bridge) (by @Rastusik)
-- [#308](https://github.com/PHP-DI/PHP-DI/pull/308): Instantiate factories using the container (`DI\factory(['FooFactory', 'create'])`)
-- Many performances improvements - some benchmarks show up to 35% performance improvements, real results may vary of course
-- Many documentation improvements (@jdreesen, @mindplay-dk, @mnapoli, @holtkamp, @Rastusik)
-- [#296](https://github.com/PHP-DI/PHP-DI/issues/296): Provide a faster `ArrayCache` implementation, mostly useful in micro-benchmarks
-
-Bugfixes:
-
-- [#257](https://github.com/PHP-DI/PHP-DI/issues/257) & [#274](https://github.com/PHP-DI/PHP-DI/issues/274): Private properties of parent classes are not injected when using annotations
-- [#300](https://github.com/PHP-DI/PHP-DI/pull/300): Exception if object definition extends an incompatible definition
-- [#306](https://github.com/PHP-DI/PHP-DI/issues/306): Errors when using parameters passed by reference (fixed by @bradynpoulsen)
-- [#318](https://github.com/PHP-DI/PHP-DI/issues/318): `Container::call()` ignores parameter's default value
-
-Internal changes:
-
-- [#276](https://github.com/PHP-DI/PHP-DI/pull/276): Tests now pass on Windows (@bgaillard)
-
-## 5.0
-
-This is the complete change log. You can also read the [migration guide](doc/migration/5.0.md) for upgrading, or [the news article](news/15-php-di-5-0-released.md) for a nicer introduction to this new version.
-
-Improvements:
-
-- Moved to an organization on GitHub: [github.com/PHP-DI/PHP-DI](https://github.com/PHP-DI/PHP-DI)
-- The package has been renamed to: from `mnapoli/php-di` to [`php-di/php-di`](https://packagist.org/packages/php-di/php-di)
-- New [Silex integration](doc/frameworks/silex.md)
-- Lighter package: from 10 to 3 Composer dependencies!
-- [#235](https://github.com/PHP-DI/PHP-DI/issues/235): `DI\link()` is now deprecated in favor of `DI\get()`. There is no BC break as `DI\link()` still works.
-- [#207](https://github.com/PHP-DI/PHP-DI/issues/207): Support for `DI\link()` in arrays
-- [#203](https://github.com/PHP-DI/PHP-DI/issues/203): New `DI\string()` helper ([documentation](doc/php-definitions.md))
-- [#208](https://github.com/PHP-DI/PHP-DI/issues/208): Support for nested definitions
-- [#226](https://github.com/PHP-DI/PHP-DI/pull/226): `DI\factory()` can now be omitted with closures:
-
- ```php
- // before
- 'My\Class' => DI\factory(function () { ... })
- // now (optional shortcut)
- 'My\Class' => function () { ... }
- ```
-- [#193](https://github.com/PHP-DI/PHP-DI/issues/193): `DI\object()->method()` now supports calling the same method twice (or more).
-- [#248](https://github.com/PHP-DI/PHP-DI/issues/248): New `DI\decorate()` helper to decorate a previously defined entry ([documentation](doc/definition-overriding.md))
-- [#215](https://github.com/PHP-DI/PHP-DI/pull/215): New `DI\add()` helper to add entries to an existing array ([documentation](doc/definition-overriding.md))
-- [#218](https://github.com/PHP-DI/PHP-DI/issues/218): `ContainerBuilder::addDefinitions()` can now take an array of definitions
-- [#211](https://github.com/PHP-DI/PHP-DI/pull/211): `ContainerBuilder::addDefinitions()` is now fluent (return `$this`)
-- [#250](https://github.com/PHP-DI/PHP-DI/issues/250): `Container::call()` now also accepts parameters not indexed by name as well as embedded definitions ([documentation](doc/container.md))
-- Various performance improvements, e.g. lower the number of files loaded, simpler architecture, …
-
-BC breaks:
-
-- PHP-DI now requires a version of PHP >= 5.4.0
-- The package is lighter by default:
- - [#251](https://github.com/PHP-DI/PHP-DI/issues/251): Annotations are disabled by default, if you use annotations enable them with `$containerBuilder->useAnnotations(true)`. Additionally the `doctrine/annotations` package isn't required by default anymore, so you also need to run `composer require doctrine/annotations`.
- - `doctrine/cache` is not installed by default anymore, you need to require it in `composer.json` (`~1.0`) if you want to configure a cache for PHP-DI
- - [#198](https://github.com/PHP-DI/PHP-DI/issues/198): `ocramius/proxy-manager` is not installed by default anymore, you need to require it in `composer.json` (`~1.0`) if you want to use **lazy injection**
-- Closures are now converted into factory definitions automatically. If you ever defined a closure as a value (e.g. to have the closure injected in a class), you need to wrap the closure with the new `DI\value()` helper.
-- [#223](https://github.com/PHP-DI/PHP-DI/issues/223): `DI\ContainerInterface` was deprecated since v4.1 and has been removed
-
-Internal changes in case you were replacing/extending some parts:
-
-- the definition sources architecture has been refactored, if you defined custom definition sources you will need to update your code (it should be much easier now)
-- [#252](https://github.com/PHP-DI/PHP-DI/pull/252): `DI\Scope` internal implementation has changed. You are encouraged to use the constants (`DI\Scope::SINGLETON` and `DI\Scope::PROTOTYPE`) instead of the static methods, but backward compatibility is kept (static methods still work).
-- [#241](https://github.com/PHP-DI/PHP-DI/issues/241): `Container::call()` now uses the *Invoker* external library
-
-## 4.4
-
-Read the [news entry](news/13-php-di-4-4-released.md).
-
-- [#185](https://github.com/PHP-DI/PHP-DI/issues/185) Support for invokable objects in `Container::call()`
-- [#192](https://github.com/PHP-DI/PHP-DI/pull/192) Support for invokable classes in `Container::call()` (will instantiate the class)
-- [#184](https://github.com/PHP-DI/PHP-DI/pull/184) Option to ignore phpdoc errors
-
-## 4.3
-
-Read the [news entry](news/11-php-di-4-3-released.md).
-
-- [#176](https://github.com/PHP-DI/PHP-DI/pull/176) New definition type for reading environment variables: `DI\env()`
-- [#181](https://github.com/PHP-DI/PHP-DI/pull/181) `DI\FactoryInterface` and `DI\InvokerInterface` are now auto-registered inside the container so that you can inject them without any configuration needed
-- [#173](https://github.com/PHP-DI/PHP-DI/pull/173) `$container->call(['MyClass', 'method]);` will get `MyClass` from the container if `method()` is not a static method
-
-## 4.2.2
-
-- Fixed [#180](https://github.com/PHP-DI/PHP-DI/pull/180): `Container::call()` with object methods (`[$object, 'method']`) is now supported
-
-## 4.2.1
-
-- Support for PHP 5.3.3, which was previously incomplete because of a bug in the reflection (there is now a workaround for this bug)
-
-But if you can, seriously avoid this (really old) PHP version and upgrade.
-
-## 4.2
-
-Read the [news entry](news/10-php-di-4-2-released.md).
-
-**Minor BC-break**: Optional parameters (that were not configured) were injected, they are now ignored, which is what naturally makes sense since they are optional.
-Example:
-
-```php
- public function __construct(Bar $bar = null)
- {
- $this->bar = $bar ?: $this->createDefaultBar();
- }
-```
-
-Before 4.2, PHP-DI would try to inject a `Bar` instance. From 4.2 and onwards, it will inject `null`.
-
-Of course, you can still explicitly define an injection for the optional parameters and that will work.
-
-All changes:
-
-* [#162](https://github.com/PHP-DI/PHP-DI/pull/162) Added `Container::call()` to call functions with dependency injection
-* [#156](https://github.com/PHP-DI/PHP-DI/issues/156) Wildcards (`*`) in definitions
-* [#164](https://github.com/PHP-DI/PHP-DI/issues/164) Prototype scope is now available for `factory()` definitions too
-* FIXED [#168](https://github.com/PHP-DI/PHP-DI/pull/168) `Container::has()` now returns false for interfaces and abstract classes that are not mapped in the definitions
-* FIXED [#171](https://github.com/PHP-DI/PHP-DI/issues/171) Optional parameters are now ignored (not injected) if not set in the definitions (see the BC-break warning above)
-
-## 4.1
-
-Read the [news entry](news/09-php-di-4-1-released.md).
-
-BC-breaks: None.
-
-* [#138](https://github.com/PHP-DI/PHP-DI/issues/138) [Container-interop](https://github.com/container-interop/container-interop) compliance
-* [#143](https://github.com/PHP-DI/PHP-DI/issues/143) Much more explicit exception messages
-* [#157](https://github.com/PHP-DI/PHP-DI/issues/157) HHVM support
-* [#158](https://github.com/PHP-DI/PHP-DI/issues/158) Improved the documentation for [Symfony 2 integration](http://php-di.org/doc/frameworks/symfony2.html)
-
-## 4.0
-
-Major changes:
-
-* The configuration format has changed ([read more here to understand why](news/06-php-di-4-0-new-definitions.md))
-
-Read the migration guide if you are using 3.x: [Migration guide from 3.x to 4.0](doc/migration/4.0.md).
-
-BC-breaks:
-
-* YAML, XML and JSON definitions have been removed, and the PHP definition format has changed (see above)
-* `ContainerSingleton` has been removed
-* You cannot configure an injection as lazy anymore, you can only configure a container entry as lazy
-* The Container constructor now takes mandatory parameters. Use the ContainerBuilder to create a Container.
-* Removed `ContainerBuilder::setDefinitionsValidation()` (no definition validation anymore)
-* `ContainerBuilder::useReflection()` is now named: `ContainerBuilder::useAutowiring()`
-* `ContainerBuilder::addDefinitionsFromFile()` is now named: `ContainerBuilder::addDefinitions()`
-* The `$proxy` parameter in `Container::get($name, $proxy = true)` hase been removed. To get a proxy, you now need to define an entry as "lazy".
-
-Other changes:
-
-* Added `ContainerInterface` and `FactoryInterface`, both implemented by the container.
-* [#115](https://github.com/PHP-DI/PHP-DI/issues/115) Added `Container::has()`
-* [#142](https://github.com/PHP-DI/PHP-DI/issues/142) Added `Container::make()` to resolve an entry
-* [#127](https://github.com/PHP-DI/PHP-DI/issues/127) Added support for cases where PHP-DI is wrapped by another container (like Acclimate): PHP-DI can now use the wrapping container to perform injections
-* [#128](https://github.com/PHP-DI/PHP-DI/issues/128) Configure entry aliases
-* [#110](https://github.com/PHP-DI/PHP-DI/issues/110) XML definitions are not supported anymore
-* [#122](https://github.com/PHP-DI/PHP-DI/issues/122) JSON definitions are not supported anymore
-* `ContainerSingleton` has finally been removed
-* Added `ContainerBuilder::buildDevContainer()` to get started with a default container very easily.
-* [#99](https://github.com/PHP-DI/PHP-DI/issues/99) Fixed "`@param` with PHP internal type throws exception"
-
-## 3.5.1
-
-* FIXED [#126](https://github.com/PHP-DI/PHP-DI/issues/126): `Container::set` without effect if a value has already been set and retrieved
-
-## 3.5
-
-Read the [news entry](news/05-php-di-3-5.md).
-
-* Importing `@Inject` and `@Injectable` annotations is now optional! It means that you don't have to write `use DI\Annotation\Inject` anymore
-* FIXED [#124](https://github.com/PHP-DI/PHP-DI/issues/124): `@Injects` annotation conflicts with other annotations
-
-## 3.4
-
-Read the [news entry](news/04-php-di-3-4.md).
-
-* [#106](https://github.com/PHP-DI/PHP-DI/pull/106) You can now define arrays of values (in YAML, PHP, …) thanks to [@unkind](https://github.com/unkind)
-* [#98](https://github.com/PHP-DI/PHP-DI/issues/98) `ContainerBuilder` is now fluent thanks to [@drdamour](https://github.com/drdamour)
-* [#101](https://github.com/PHP-DI/PHP-DI/pull/101) Optional parameters are now supported: if you don't define a value to inject, their default value will be used
-* XML definitions have been deprecated, there weren't even documented and were not maintained. They will be removed in 4.0.
-* FIXED [#100](https://github.com/PHP-DI/PHP-DI/issues/100): bug for lazy injection in constructors
-
-## 3.3
-
-Read the [news entry](news/03-php-di-3-3.md).
-
-* Inject dependencies on an existing instance with `Container::injectOn` (work from [Jeff Flitton](https://github.com/jflitton): [#89](https://github.com/PHP-DI/PHP-DI/pull/89)).
-* [#86](https://github.com/PHP-DI/PHP-DI/issues/86): Optimized definition lookup (faster)
-* FIXED [#87](https://github.com/PHP-DI/PHP-DI/issues/87): Rare bug in the `PhpDocParser`, fixed by [drdamour](https://github.com/drdamour)
-
-## 3.2
-
-Read the [news entry](news/02-php-di-3-2.md).
-
-Small BC-break: PHP-DI 3.0 and 3.1 injected properties before calling the constructor. This was confusing and [not supported for internal classes](https://github.com/PHP-DI/PHP-DI/issues/74).
-From 3.2 and on, properties are injected after calling the constructor.
-
-* **[Lazy injection](doc/lazy-injection.md)**: it is now possible to use lazy injection on properties and methods (setters and constructors).
-* Lazy dependencies are now proxies that extend the class they proxy, so type-hinting works.
-* Addition of the **`ContainerBuilder`** object, that helps to [create and configure a `Container`](doc/container-configuration.md).
-* Some methods for configuring the Container have gone **deprecated** in favor of the `ContainerBuilder`. Fear not, these deprecated methods will remain until next major version (4.0).
- * `Container::useReflection`, use ContainerBuilder::useReflection instead
- * `Container::useAnnotations`, use ContainerBuilder::useAnnotations instead
- * `Container::setDefinitionCache`, use ContainerBuilder::setDefinitionCache instead
- * `Container::setDefinitionsValidation`, use ContainerBuilder::setDefinitionsValidation instead
-* The container is now auto-registered (as 'DI\Container'). You can now inject the container without registering it.
-
-## 3.1.1
-
-* Value definitions (`$container->set('foo', 80)`) are not cached anymore
-* FIXED [#82](https://github.com/PHP-DI/PHP-DI/issues/82): Serialization error when using a cache
-
-## 3.1
-
-Read the [news entry](news/01-php-di-3-1.md).
-
-* Zend Framework 1 integration through the [PHP-DI-ZF1 project](https://github.com/PHP-DI/PHP-DI-ZF1)
-* Fixed the order of priorities when you mix different definition sources (reflection, annotations, files, …). See [Definition overriding](doc/definition-overriding.md)
-* Now possible to define null values with `$container->set('foo', null)` (see [#79](https://github.com/PHP-DI/PHP-DI/issues/79)).
-* Deprecated usage of `ContainerSingleton`, will be removed in next major version (4.0)
-
-## 3.0.6
-
-* FIXED [#76](https://github.com/PHP-DI/PHP-DI/issues/76): Definition conflict when setting a closure for a class name
-
-## 3.0.5
-
-* FIXED [#70](https://github.com/PHP-DI/PHP-DI/issues/70): Definition conflict when setting a value for a class name
-
-## 3.0.4
-
-* FIXED [#69](https://github.com/PHP-DI/PHP-DI/issues/69): YamlDefinitionFileLoader crashes if YAML file is empty
-
-## 3.0.3
-
-* Fixed over-restrictive dependencies in composer.json
-
-## 3.0.2
-
-* [#64](https://github.com/PHP-DI/PHP-DI/issues/64): Non PHP-DI exceptions are not captured-rethrown anymore when injecting dependencies (cleaner stack trace)
-
-## 3.0.1
-
-* [#62](https://github.com/PHP-DI/PHP-DI/issues/62): When using aliases, definitions are now merged
-
-## 3.0
-
-Major compatibility breaks with 2.x.
-
-* The container is no longer a Singleton (but `ContainerSingleton::getInstance()` is available for fools who like it)
-* Setter injection
-* Constructor injection
-* Scopes: singleton (share the same instance of the class) or prototype (create a new instance each time it is fetched). Defined at class level.
-* Configuration is reworked from scratch. Now every configuration backend can do 100% of the job.
-* Provided configuration backends:
- * Reflection
- * Annotations: @Inject, @Injectable
- * PHP code (`Container::set()`)
- * PHP array
- * YAML file
-* As a consequence, annotations are not mandatory anymore, all functionalities can be used with or without annotations.
-* Renamed `DI\Annotations\` to `DI\Annotation\`
-* `Container` no longer implements ArrayAccess, use only `$container->get($key)` now
-* ZF1 integration broken and removed (work in progress for next releases)
-* Code now follows PSR1 and PSR2 coding styles
-* FIXED: [#58](https://github.com/PHP-DI/PHP-DI/issues/58) Getting a proxy of an alias didn't work
-
-## 2.1
-
-* `use` statements to import classes from other namespaces are now taken into account with the `@var` annotation
-* Updated and lightened the dependencies : `doctrine/common` has been replaced with more specific `doctrine/annotations` and `doctrine/cache`
-
-## 2.0
-
-Major compatibility breaks with 1.x.
-
-* `Container::resolveDependencies()` has been renamed to `Container::injectAll()`
-* Dependencies are now injected **before** the constructor is called, and thus are available in the constructor
-* Merged `@Value` annotation with `@Inject`: no difference between value and bean injection anymore
-* Container implements ArrayAccess for get() and set() (`$container['db.host'] = 'localhost';`)
-* Ini configuration files removed: configuration is done in PHP
-* Allow to define beans within closures for lazy-loading
-* Switched to MIT License
-
-Warning:
-
-* If you use PHP 5.3 and __wakeup() methods, they will be called when PHP-DI creates new instances of those classes.
-
-## 1.1
-
-* Caching of annotations based on Doctrine caches
-
-## 1.0
-
-* DependencyManager renamed to Container
-* Refactored basic Container usage with `get` and `set`
-* Allow named injection `@Inject(name="")`
-* Zend Framework integration
+++ /dev/null
-{
- "name": "php-di/php-di",
- "type": "library",
- "description": "The dependency injection container for humans",
- "keywords": ["di", "dependency injection", "container"],
- "homepage": "http://php-di.org/",
- "license": "MIT",
- "autoload": {
- "psr-4": {
- "DI\\": "src/DI/"
- },
- "files": [
- "src/DI/functions.php"
- ]
- },
- "autoload-dev": {
- "psr-4": {
- "DI\\Test\\IntegrationTest\\": "tests/IntegrationTest/",
- "DI\\Test\\UnitTest\\": "tests/UnitTest/"
- }
- },
- "require": {
- "php": ">=5.4.0",
- "container-interop/container-interop": "~1.0",
- "php-di/invoker": "^1.0.1",
- "php-di/phpdoc-reader": "~2.0"
- },
- "require-dev": {
- "phpunit/phpunit": "~4.5",
- "mnapoli/phpunit-easymock": "~0.1.4",
- "doctrine/cache": "~1.4",
- "doctrine/annotations": "~1.2",
- "ocramius/proxy-manager": "~1.0"
- },
- "replace": {
- "mnapoli/php-di": "*"
- },
- "suggest": {
- "doctrine/cache": "Install it if you want to use the cache (version ~1.4)",
- "doctrine/annotations": "Install it if you want to use annotations (version ~1.2)",
- "ocramius/proxy-manager": "Install it if you want to use lazy injection (version ~1.0)"
- }
-}
+++ /dev/null
-baseUrl: http://php-di.org
-
-scripts:
- before:
- - lessc --clean-css website/less/main.less website/css/all.min.css
-
-menu:
- items:
- introduction:
- section: Introduction
- items:
- getting-started:
- text: Getting started
- url: doc/getting-started.html
- understanding-di:
- text: Understanding dependency injection
- url: doc/understanding-di.html
- best-practices:
- text: "\"Best practices\" guide"
- url: doc/best-practices.html
- usage:
- section: Usage
- items:
- container-configuration:
- text: Configuring the container
- url: doc/container-configuration.html
- container:
- text: Using the container
- url: doc/container.html
- definition:
- section: Definitions
- items:
- introduction:
- text: Introduction
- url: doc/definition.html
- autowiring:
- text: Autowiring
- url: doc/autowiring.html
- php:
- text: PHP definitions
- url: doc/php-definitions.html
- annotations:
- text: Annotations
- url: doc/annotations.html
- definition-overriding:
- text: Definition extensions and overriding
- url: doc/definition-overriding.html
- frameworks:
- section: Frameworks
- items:
- symfony2:
- text: Symfony 2
- url: doc/frameworks/symfony2.html
- silex:
- text: Silex
- url: doc/frameworks/silex.html
- zf2:
- text: Zend Framework 2
- url: doc/frameworks/zf2.html
- zf1:
- text: Zend Framework 1
- url: doc/frameworks/zf1.html
- silly:
- text: Silly
- url: doc/frameworks/silly.html
- advanced:
- section: Advanced topics
- items:
- performances:
- text: Performances
- url: doc/performances.html
- scopes:
- text: Scopes
- url: doc/scopes.html
- lazy-injection:
- text: Lazy injection
- url: doc/lazy-injection.html
- inject-on-instance:
- text: Inject on an existing instance
- url: doc/inject-on-instance.html
- environments:
- text: Injections depending on the environment
- url: doc/environments.html
- migration:
- section: Migration guides
- items:
- 4:
- text: From PHP-DI 3.x to 4.0
- url: doc/migration/4.0.html
- 5:
- text: From PHP-DI 4.x to 5.0
- url: doc/migration/5.0.html
- internals:
- section: Internals
- items:
- contributing:
- text: Contributing
- url: contributing.html
- how-it-works:
- text: How PHP-DI works
- url: doc/how-it-works.html
- versions:
- section: Old documentation
- items:
- v3:
- text: PHP-DI 3.x
- absoluteUrl: https://github.com/PHP-DI/PHP-DI/tree/3.x/doc
- v4:
- text: PHP-DI 4.x
- absoluteUrl: https://github.com/PHP-DI/PHP-DI/tree/4.x/doc
+++ /dev/null
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- phpunit -c phpunit.xml
--->
-<phpunit backupGlobals="false"
- backupStaticAttributes="false"
- colors="true"
- convertErrorsToExceptions="true"
- convertNoticesToExceptions="true"
- convertWarningsToExceptions="true"
- syntaxCheck="true"
- forceCoversAnnotation="true"
- bootstrap="./vendor/autoload.php">
-
- <testsuites>
- <testsuite name="unit">
- <directory>./tests/UnitTest/</directory>
- </testsuite>
- <testsuite name="integration">
- <directory>./tests/IntegrationTest/</directory>
- </testsuite>
- </testsuites>
-
- <filter>
- <whitelist processUncoveredFilesFromWhitelist="true">
- <directory suffix=".php">src</directory>
- </whitelist>
- </filter>
-
-</phpunit>
+++ /dev/null
-<?php
-/**
- * PHP-DI
- *
- * @link http://php-di.org/
- * @copyright Matthieu Napoli (http://mnapoli.fr/)
- * @license http://www.opensource.org/licenses/mit-license.php MIT (see the LICENSE file)
- */
-
-namespace DI\Annotation;
-
-use DI\Definition\Exception\AnnotationException;
-
-/**
- * "Inject" annotation
- *
- * Marks a property or method as an injection point
- *
- * @Annotation
- * @Target({"METHOD","PROPERTY"})
- *
- * @author Matthieu Napoli <matthieu@mnapoli.fr>
- */
-final class Inject
-{
- /**
- * Entry name
- * @var string
- */
- private $name;
-
- /**
- * Parameters, indexed by the parameter number (index) or name
- *
- * Used if the annotation is set on a method
- * @var array
- */
- private $parameters = [];
-
- /**
- * @param array $values
- */
- public function __construct(array $values)
- {
- // Process the parameters as a list AND as a parameter array (we don't know on what the annotation is)
-
- // @Inject(name="foo")
- if (isset($values['name']) && is_string($values['name'])) {
- $this->name = $values['name'];
- return;
- }
-
- // @Inject
- if (! isset($values['value'])) {
- return;
- }
-
- $values = $values['value'];
-
- // @Inject("foo")
- if (is_string($values)) {
- $this->name = $values;
- }
-
- // @Inject({...}) on a method
- if (is_array($values)) {
- foreach ($values as $key => $value) {
- if (! is_string($value)) {
- throw new AnnotationException(sprintf(
- '@Inject({"param" = "value"}) expects "value" to be a string, %s given.',
- json_encode($value)
- ));
- }
-
- $this->parameters[$key] = $value;
- }
- }
- }
-
- /**
- * @return string Name of the entry to inject
- */
- public function getName()
- {
- return $this->name;
- }
-
- /**
- * @return array Parameters, indexed by the parameter number (index) or name
- */
- public function getParameters()
- {
- return $this->parameters;
- }
-}
+++ /dev/null
-<?php
-/**
- * PHP-DI
- *
- * @link http://php-di.org/
- * @copyright Matthieu Napoli (http://mnapoli.fr/)
- * @license http://www.opensource.org/licenses/mit-license.php MIT (see the LICENSE file)
- */
-
-namespace DI\Annotation;
-
-use DI\Scope;
-use UnexpectedValueException;
-
-/**
- * "Injectable" annotation
- *
- * Marks a class as injectable
- *
- * @Annotation
- * @Target("CLASS")
- *
- * @author Domenic Muskulus <domenic@muskulus.eu>
- * @author Matthieu Napoli <matthieu@mnapoli.fr>
- */
-final class Injectable
-{
- /**
- * The scope of an class: prototype, singleton
- * @var string|null
- */
- private $scope;
-
- /**
- * Should the object be lazy-loaded
- * @var boolean|null
- */
- private $lazy;
-
- /**
- * @param array $values
- */
- public function __construct(array $values)
- {
- if (isset($values['scope'])) {
- if ($values['scope'] === 'prototype') {
- $this->scope = Scope::PROTOTYPE;
- } elseif ($values['scope'] === 'singleton') {
- $this->scope = Scope::SINGLETON;
- } else {
- throw new UnexpectedValueException(sprintf("Value '%s' is not a valid scope", $values['scope']));
- }
- }
- if (isset($values['lazy'])) {
- $this->lazy = (boolean) $values['lazy'];
- }
- }
-
- /**
- * @return string|null
- */
- public function getScope()
- {
- return $this->scope;
- }
-
- /**
- * @return boolean|null
- */
- public function isLazy()
- {
- return $this->lazy;
- }
-}
+++ /dev/null
-<?php
-/**
- * PHP-DI
- *
- * @link http://php-di.org/
- * @copyright Matthieu Napoli (http://mnapoli.fr/)
- * @license http://www.opensource.org/licenses/mit-license.php MIT (see the LICENSE file)
- */
-
-namespace DI\Cache;
-
-use Doctrine\Common\Cache\Cache;
-use Doctrine\Common\Cache\ClearableCache;
-use Doctrine\Common\Cache\FlushableCache;
-
-/**
- * Simple implementation of a cache based on an array.
- *
- * This implementation can be used instead of Doctrine's ArrayCache for
- * better performances (because simpler implementation).
- *
- * The code is based on Doctrine's ArrayCache provider:
- * @see \Doctrine\Common\Cache\ArrayCache
- * @link www.doctrine-project.org
- * @author Benjamin Eberlei <kontakt@beberlei.de>
- * @author Guilherme Blanco <guilhermeblanco@hotmail.com>
- * @author Jonathan Wage <jonwage@gmail.com>
- * @author Roman Borschel <roman@code-factory.org>
- * @author David Abdemoulaie <dave@hobodave.com>
- */
-class ArrayCache implements Cache, FlushableCache, ClearableCache
-{
- /**
- * @var array $data
- */
- private $data = [];
-
- public function fetch($id)
- {
- return $this->contains($id) ? $this->data[$id] : false;
- }
-
- public function contains($id)
- {
- // isset() is required for performance optimizations, to avoid unnecessary function calls to array_key_exists.
- return isset($this->data[$id]) || array_key_exists($id, $this->data);
- }
-
- public function save($id, $data, $lifeTime = 0)
- {
- $this->data[$id] = $data;
-
- return true;
- }
-
- public function delete($id)
- {
- unset($this->data[$id]);
-
- return true;
- }
-
- public function getStats()
- {
- return null;
- }
-
- public function flushAll()
- {
- $this->data = array();
-
- return true;
- }
-
- public function deleteAll()
- {
- return $this->flushAll();
- }
-}
+++ /dev/null
-<?php
-/**
- * PHP-DI
- *
- * @link http://php-di.org/
- * @copyright Matthieu Napoli (http://mnapoli.fr/)
- * @license http://www.opensource.org/licenses/mit-license.php MIT (see the LICENSE file)
- */
-
-namespace DI;
-
-use DI\Definition\ObjectDefinition;
-use DI\Definition\Definition;
-use DI\Definition\FactoryDefinition;
-use DI\Definition\InstanceDefinition;
-use DI\Definition\Resolver\ResolverDispatcher;
-use DI\Definition\Source\CachedDefinitionSource;
-use DI\Definition\Source\DefinitionSource;
-use DI\Definition\Source\MutableDefinitionSource;
-use DI\Definition\Helper\DefinitionHelper;
-use DI\Definition\Resolver\DefinitionResolver;
-use DI\Invoker\DefinitionParameterResolver;
-use DI\Proxy\ProxyFactory;
-use Exception;
-use Interop\Container\ContainerInterface;
-use InvalidArgumentException;
-use Invoker\Invoker;
-use Invoker\ParameterResolver\AssociativeArrayResolver;
-use Invoker\ParameterResolver\Container\TypeHintContainerResolver;
-use Invoker\ParameterResolver\DefaultValueResolver;
-use Invoker\ParameterResolver\NumericArrayResolver;
-use Invoker\ParameterResolver\ResolverChain;
-
-/**
- * Dependency Injection Container.
- *
- * @author Matthieu Napoli <matthieu@mnapoli.fr>
- */
-class Container implements ContainerInterface, FactoryInterface, \DI\InvokerInterface
-{
- /**
- * Map of entries with Singleton scope that are already resolved.
- * @var array
- */
- private $singletonEntries = [];
-
- /**
- * @var DefinitionSource
- */
- private $definitionSource;
-
- /**
- * @var DefinitionResolver
- */
- private $definitionResolver;
-
- /**
- * Array of entries being resolved. Used to avoid circular dependencies and infinite loops.
- * @var array
- */
- private $entriesBeingResolved = [];
-
- /**
- * @var \Invoker\InvokerInterface|null
- */
- private $invoker;
-
- /**
- * Container that wraps this container. If none, points to $this.
- *
- * @var ContainerInterface
- */
- private $wrapperContainer;
-
- /**
- * Use the ContainerBuilder to ease constructing the Container.
- *
- * @see ContainerBuilder
- *
- * @param DefinitionSource $definitionSource
- * @param ProxyFactory $proxyFactory
- * @param ContainerInterface $wrapperContainer If the container is wrapped by another container.
- */
- public function __construct(
- DefinitionSource $definitionSource,
- ProxyFactory $proxyFactory,
- ContainerInterface $wrapperContainer = null
- ) {
- $this->wrapperContainer = $wrapperContainer ?: $this;
-
- $this->definitionSource = $definitionSource;
- $this->definitionResolver = new ResolverDispatcher($this->wrapperContainer, $proxyFactory);
-
- // Auto-register the container
- $this->singletonEntries['DI\Container'] = $this;
- $this->singletonEntries['DI\FactoryInterface'] = $this;
- $this->singletonEntries['DI\InvokerInterface'] = $this;
- }
-
- /**
- * Returns an entry of the container by its name.
- *
- * @param string $name Entry name or a class name.
- *
- * @throws InvalidArgumentException The name parameter must be of type string.
- * @throws DependencyException Error while resolving the entry.
- * @throws NotFoundException No entry found for the given name.
- * @return mixed
- */
- public function get($name)
- {
- if (! is_string($name)) {
- throw new InvalidArgumentException(sprintf(
- 'The name parameter must be of type string, %s given',
- is_object($name) ? get_class($name) : gettype($name)
- ));
- }
-
- // Try to find the entry in the singleton map
- if (array_key_exists($name, $this->singletonEntries)) {
- return $this->singletonEntries[$name];
- }
-
- $definition = $this->definitionSource->getDefinition($name);
- if (! $definition) {
- throw new NotFoundException("No entry or class found for '$name'");
- }
-
- $value = $this->resolveDefinition($definition);
-
- // If the entry is singleton, we store it to always return it without recomputing it
- if ($definition->getScope() === Scope::SINGLETON) {
- $this->singletonEntries[$name] = $value;
- }
-
- return $value;
- }
-
- /**
- * Build an entry of the container by its name.
- *
- * This method behave like get() except it forces the scope to "prototype",
- * which means the definition of the entry will be re-evaluated each time.
- * For example, if the entry is a class, then a new instance will be created each time.
- *
- * This method makes the container behave like a factory.
- *
- * @param string $name Entry name or a class name.
- * @param array $parameters Optional parameters to use to build the entry. Use this to force specific parameters
- * to specific values. Parameters not defined in this array will be resolved using
- * the container.
- *
- * @throws InvalidArgumentException The name parameter must be of type string.
- * @throws DependencyException Error while resolving the entry.
- * @throws NotFoundException No entry found for the given name.
- * @return mixed
- */
- public function make($name, array $parameters = [])
- {
- if (! is_string($name)) {
- throw new InvalidArgumentException(sprintf(
- 'The name parameter must be of type string, %s given',
- is_object($name) ? get_class($name) : gettype($name)
- ));
- }
-
- $definition = $this->definitionSource->getDefinition($name);
- if (! $definition) {
- // Try to find the entry in the singleton map
- if (array_key_exists($name, $this->singletonEntries)) {
- return $this->singletonEntries[$name];
- }
-
- throw new NotFoundException("No entry or class found for '$name'");
- }
-
- return $this->resolveDefinition($definition, $parameters);
- }
-
- /**
- * Test if the container can provide something for the given name.
- *
- * @param string $name Entry name or a class name.
- *
- * @throws InvalidArgumentException The name parameter must be of type string.
- * @return bool
- */
- public function has($name)
- {
- if (! is_string($name)) {
- throw new InvalidArgumentException(sprintf(
- 'The name parameter must be of type string, %s given',
- is_object($name) ? get_class($name) : gettype($name)
- ));
- }
-
- if (array_key_exists($name, $this->singletonEntries)) {
- return true;
- }
-
- $definition = $this->definitionSource->getDefinition($name);
- if ($definition === null) {
- return false;
- }
-
- return $this->definitionResolver->isResolvable($definition);
- }
-
- /**
- * Inject all dependencies on an existing instance
- *
- * @param object $instance Object to perform injection upon
- * @throws InvalidArgumentException
- * @throws DependencyException Error while injecting dependencies
- * @return object $instance Returns the same instance
- */
- public function injectOn($instance)
- {
- $objectDefinition = $this->definitionSource->getDefinition(get_class($instance));
- if (! $objectDefinition instanceof ObjectDefinition) {
- return $instance;
- }
-
- $definition = new InstanceDefinition($instance, $objectDefinition);
-
- $this->definitionResolver->resolve($definition);
-
- return $instance;
- }
-
- /**
- * Call the given function using the given parameters.
- *
- * Missing parameters will be resolved from the container.
- *
- * @param callable $callable Function to call.
- * @param array $parameters Parameters to use. Can be indexed by the parameter names
- * or not indexed (same order as the parameters).
- * The array can also contain DI definitions, e.g. DI\get().
- *
- * @return mixed Result of the function.
- */
- public function call($callable, array $parameters = [])
- {
- return $this->getInvoker()->call($callable, $parameters);
- }
-
- /**
- * Define an object or a value in the container.
- *
- * @param string $name Entry name
- * @param mixed|DefinitionHelper $value Value, use definition helpers to define objects
- */
- public function set($name, $value)
- {
- if ($value instanceof DefinitionHelper) {
- $value = $value->getDefinition($name);
- } elseif ($value instanceof \Closure) {
- $value = new FactoryDefinition($name, $value);
- }
-
- if ($value instanceof Definition) {
- $this->setDefinition($name, $value);
- } else {
- $this->singletonEntries[$name] = $value;
- }
- }
-
- /**
- * Resolves a definition.
- *
- * Checks for circular dependencies while resolving the definition.
- *
- * @param Definition $definition
- * @param array $parameters
- *
- * @throws DependencyException Error while resolving the entry.
- * @return mixed
- */
- private function resolveDefinition(Definition $definition, array $parameters = [])
- {
- $entryName = $definition->getName();
-
- // Check if we are already getting this entry -> circular dependency
- if (isset($this->entriesBeingResolved[$entryName])) {
- throw new DependencyException("Circular dependency detected while trying to resolve entry '$entryName'");
- }
- $this->entriesBeingResolved[$entryName] = true;
-
- // Resolve the definition
- try {
- $value = $this->definitionResolver->resolve($definition, $parameters);
- } catch (Exception $exception) {
- unset($this->entriesBeingResolved[$entryName]);
- throw $exception;
- }
-
- unset($this->entriesBeingResolved[$entryName]);
-
- return $value;
- }
-
- private function setDefinition($name, Definition $definition)
- {
- if ($this->definitionSource instanceof CachedDefinitionSource) {
- throw new \LogicException('You cannot set a definition at runtime on a container that has a cache configured. Doing so would risk caching the definition for the next execution, where it might be different. You can either put your definitions in a file, remove the cache or ->set() a raw value directly (PHP object, string, int, ...) instead of a PHP-DI definition.');
- }
-
- if (! $this->definitionSource instanceof MutableDefinitionSource) {
- // This can happen if you instantiate the container yourself
- throw new \LogicException('The container has not been initialized correctly');
- }
-
- // Clear existing entry if it exists
- if (array_key_exists($name, $this->singletonEntries)) {
- unset($this->singletonEntries[$name]);
- }
-
- $this->definitionSource->addDefinition($definition);
- }
-
- /**
- * @return \Invoker\InvokerInterface
- */
- private function getInvoker()
- {
- if (! $this->invoker) {
- $parameterResolver = new ResolverChain([
- new DefinitionParameterResolver($this->definitionResolver),
- new NumericArrayResolver,
- new AssociativeArrayResolver,
- new DefaultValueResolver,
- new TypeHintContainerResolver($this->wrapperContainer),
- ]);
-
- $this->invoker = new Invoker($parameterResolver, $this);
- }
-
- return $this->invoker;
- }
-}
+++ /dev/null
-<?php
-/**
- * PHP-DI
- *
- * @link http://php-di.org/
- * @copyright Matthieu Napoli (http://mnapoli.fr/)
- * @license http://www.opensource.org/licenses/mit-license.php MIT (see the LICENSE file)
- */
-
-namespace DI;
-
-use DI\Definition\Source\AnnotationReader;
-use DI\Definition\Source\DefinitionArray;
-use DI\Definition\Source\CachedDefinitionSource;
-use DI\Definition\Source\DefinitionSource;
-use DI\Definition\Source\DefinitionFile;
-use DI\Definition\Source\Autowiring;
-use DI\Definition\Source\SourceChain;
-use DI\Proxy\ProxyFactory;
-use Doctrine\Common\Cache\Cache;
-use Interop\Container\ContainerInterface;
-use InvalidArgumentException;
-
-/**
- * Helper to create and configure a Container.
- *
- * With the default options, the container created is appropriate for the development environment.
- *
- * Example:
- *
- * $builder = new ContainerBuilder();
- * $container = $builder->build();
- *
- * @since 3.2
- * @author Matthieu Napoli <matthieu@mnapoli.fr>
- */
-class ContainerBuilder
-{
- /**
- * Name of the container class, used to create the container.
- * @var string
- */
- private $containerClass;
-
- /**
- * @var boolean
- */
- private $useAutowiring = true;
-
- /**
- * @var boolean
- */
- private $useAnnotations = false;
-
- /**
- * @var boolean
- */
- private $ignorePhpDocErrors = false;
-
- /**
- * @var Cache
- */
- private $cache;
-
- /**
- * If true, write the proxies to disk to improve performances.
- * @var boolean
- */
- private $writeProxiesToFile = false;
-
- /**
- * Directory where to write the proxies (if $writeProxiesToFile is enabled).
- * @var string
- */
- private $proxyDirectory;
-
- /**
- * If PHP-DI is wrapped in another container, this references the wrapper.
- * @var ContainerInterface
- */
- private $wrapperContainer;
-
- /**
- * @var DefinitionSource[]
- */
- private $definitionSources = [];
-
- /**
- * Build a container configured for the dev environment.
- *
- * @return Container
- */
- public static function buildDevContainer()
- {
- $builder = new self();
- return $builder->build();
- }
-
- /**
- * @param string $containerClass Name of the container class, used to create the container.
- */
- public function __construct($containerClass = 'DI\Container')
- {
- $this->containerClass = $containerClass;
- }
-
- /**
- * Build and return a container.
- *
- * @return Container
- */
- public function build()
- {
- $sources = array_reverse($this->definitionSources);
- if ($this->useAnnotations) {
- $sources[] = new AnnotationReader($this->ignorePhpDocErrors);
- } elseif ($this->useAutowiring) {
- $sources[] = new Autowiring();
- }
-
- $chain = new SourceChain($sources);
-
- if ($this->cache) {
- $source = new CachedDefinitionSource($chain, $this->cache);
- $chain->setRootDefinitionSource($source);
- } else {
- $source = $chain;
- // Mutable definition source
- $source->setMutableDefinitionSource(new DefinitionArray());
- }
-
- $proxyFactory = new ProxyFactory($this->writeProxiesToFile, $this->proxyDirectory);
-
- $containerClass = $this->containerClass;
-
- return new $containerClass($source, $proxyFactory, $this->wrapperContainer);
- }
-
- /**
- * Enable or disable the use of autowiring to guess injections.
- *
- * Enabled by default.
- *
- * @param boolean $bool
- * @return ContainerBuilder
- */
- public function useAutowiring($bool)
- {
- $this->useAutowiring = $bool;
- return $this;
- }
-
- /**
- * Enable or disable the use of annotations to guess injections.
- *
- * Disabled by default.
- *
- * @param boolean $bool
- * @return ContainerBuilder
- */
- public function useAnnotations($bool)
- {
- $this->useAnnotations = $bool;
- return $this;
- }
-
- /**
- * Enable or disable ignoring phpdoc errors (non-existent classes in `@param` or `@var`)
- *
- * @param boolean $bool
- * @return ContainerBuilder
- */
- public function ignorePhpDocErrors($bool)
- {
- $this->ignorePhpDocErrors = $bool;
- return $this;
- }
-
- /**
- * Enables the use of a cache for the definitions.
- *
- * @param Cache $cache Cache backend to use
- * @return ContainerBuilder
- */
- public function setDefinitionCache(Cache $cache)
- {
- $this->cache = $cache;
- return $this;
- }
-
- /**
- * Configure the proxy generation
- *
- * For dev environment, use writeProxiesToFile(false) (default configuration)
- * For production environment, use writeProxiesToFile(true, 'tmp/proxies')
- *
- * @param boolean $writeToFile If true, write the proxies to disk to improve performances
- * @param string|null $proxyDirectory Directory where to write the proxies
- * @return ContainerBuilder
- *
- * @throws InvalidArgumentException when writeToFile is set to true and the proxy directory is null
- */
- public function writeProxiesToFile($writeToFile, $proxyDirectory = null)
- {
- $this->writeProxiesToFile = $writeToFile;
-
- if ($writeToFile && $proxyDirectory === null) {
- throw new InvalidArgumentException(
- "The proxy directory must be specified if you want to write proxies on disk"
- );
- }
- $this->proxyDirectory = $proxyDirectory;
-
- return $this;
- }
-
- /**
- * If PHP-DI's container is wrapped by another container, we can
- * set this so that PHP-DI will use the wrapper rather than itself for building objects.
- *
- * @param ContainerInterface $otherContainer
- * @return $this
- */
- public function wrapContainer(ContainerInterface $otherContainer)
- {
- $this->wrapperContainer = $otherContainer;
-
- return $this;
- }
-
- /**
- * Add definitions to the container.
- *
- * @param string|array|DefinitionSource $definitions Can be an array of definitions, the
- * name of a file containing definitions
- * or a DefinitionSource object.
- * @return $this
- */
- public function addDefinitions($definitions)
- {
- if (is_string($definitions)) {
- // File
- $definitions = new DefinitionFile($definitions);
- } elseif (is_array($definitions)) {
- $definitions = new DefinitionArray($definitions);
- } elseif (! $definitions instanceof DefinitionSource) {
- throw new InvalidArgumentException(sprintf(
- '%s parameter must be a string, an array or a DefinitionSource object, %s given',
- 'ContainerBuilder::addDefinitions()',
- is_object($definitions) ? get_class($definitions) : gettype($definitions)
- ));
- }
-
- $this->definitionSources[] = $definitions;
-
- return $this;
- }
-}
+++ /dev/null
-<?php
-/**
- * PHP-DI
- *
- * @link http://php-di.org/
- * @copyright Matthieu Napoli (http://mnapoli.fr/)
- * @license http://www.opensource.org/licenses/mit-license.php MIT (see the LICENSE file)
- */
-
-namespace DI;
-
-use DI\Definition\Definition;
-use DI\Definition\Dumper\DefinitionDumperDispatcher;
-
-/**
- * Debug utilities.
- *
- * @author Matthieu Napoli <matthieu@mnapoli.fr>
- */
-class Debug
-{
- /**
- * Dump the definition to a string.
- *
- * @param Definition $definition
- *
- * @return string
- */
- public static function dumpDefinition(Definition $definition)
- {
- static $dumper;
-
- if (! $dumper) {
- $dumper = new DefinitionDumperDispatcher();
- }
-
- return $dumper->dump($definition);
- }
-}
+++ /dev/null
-<?php
-/**
- * PHP-DI
- *
- * @link http://php-di.org/
- * @copyright Matthieu Napoli (http://mnapoli.fr/)
- * @license http://www.opensource.org/licenses/mit-license.php MIT (see the LICENSE file)
- */
-
-namespace DI\Definition;
-
-use DI\Scope;
-
-/**
- * Defines an alias from an entry to another.
- *
- * @author Matthieu Napoli <matthieu@mnapoli.fr>
- */
-class AliasDefinition implements CacheableDefinition
-{
- /**
- * Entry name
- * @var string
- */
- private $name;
-
- /**
- * Name of the target entry
- * @var string
- */
- private $targetEntryName;
-
- /**
- * @param string $name Entry name
- * @param string $targetEntryName Name of the target entry
- */
- public function __construct($name, $targetEntryName)
- {
- $this->name = $name;
- $this->targetEntryName = $targetEntryName;
- }
-
- /**
- * @return string Entry name
- */
- public function getName()
- {
- return $this->name;
- }
-
- /**
- * {@inheritdoc}
- */
- public function getScope()
- {
- return Scope::PROTOTYPE;
- }
-
- /**
- * @return string
- */
- public function getTargetEntryName()
- {
- return $this->targetEntryName;
- }
-}
+++ /dev/null
-<?php
-/**
- * PHP-DI
- *
- * @link http://php-di.org/
- * @copyright Matthieu Napoli (http://mnapoli.fr/)
- * @license http://www.opensource.org/licenses/mit-license.php MIT (see the LICENSE file)
- */
-
-namespace DI\Definition;
-
-use DI\Scope;
-
-/**
- * Definition of an array containing values or references.
- *
- * @since 5.0
- * @author Matthieu Napoli <matthieu@mnapoli.fr>
- */
-class ArrayDefinition implements Definition
-{
- /**
- * Entry name
- * @var string
- */
- private $name;
-
- /**
- * @var array
- */
- private $values;
-
- /**
- * @param string $name Entry name
- * @param array $values
- */
- public function __construct($name, array $values)
- {
- $this->name = $name;
- $this->values = $values;
- }
-
- /**
- * @return string Entry name
- */
- public function getName()
- {
- return $this->name;
- }
-
- /**
- * {@inheritdoc}
- */
- public function getScope()
- {
- return Scope::SINGLETON;
- }
-
- /**
- * @return array
- */
- public function getValues()
- {
- return $this->values;
- }
-}
+++ /dev/null
-<?php
-/**
- * PHP-DI
- *
- * @link http://php-di.org/
- * @copyright Matthieu Napoli (http://mnapoli.fr/)
- * @license http://www.opensource.org/licenses/mit-license.php MIT (see the LICENSE file)
- */
-
-namespace DI\Definition;
-
-use DI\Definition\Exception\DefinitionException;
-
-/**
- * Extends an array definition by adding new elements into it.
- *
- * @since 5.0
- * @author Matthieu Napoli <matthieu@mnapoli.fr>
- */
-class ArrayDefinitionExtension extends ArrayDefinition implements HasSubDefinition
-{
- /**
- * @var ArrayDefinition
- */
- private $subDefinition;
-
- /**
- * {@inheritdoc}
- */
- public function getValues()
- {
- if (! $this->subDefinition) {
- return parent::getValues();
- }
-
- return array_merge($this->subDefinition->getValues(), parent::getValues());
- }
-
- /**
- * @return string
- */
- public function getSubDefinitionName()
- {
- return $this->getName();
- }
-
- /**
- * {@inheritdoc}
- */
- public function setSubDefinition(Definition $definition)
- {
- if (! $definition instanceof ArrayDefinition) {
- throw new DefinitionException(sprintf(
- 'Definition %s tries to add array entries but the previous definition is not an array',
- $this->getName()
- ));
- }
-
- $this->subDefinition = $definition;
- }
-}
+++ /dev/null
-<?php
-/**
- * PHP-DI
- *
- * @link http://php-di.org/
- * @copyright Matthieu Napoli (http://mnapoli.fr/)
- * @license http://www.opensource.org/licenses/mit-license.php MIT (see the LICENSE file)
- */
-
-namespace DI\Definition;
-
-/**
- * Cacheable definition
- *
- * @author Matthieu Napoli <matthieu@mnapoli.fr>
- */
-interface CacheableDefinition extends Definition
-{
-}
+++ /dev/null
-<?php
-/**
- * PHP-DI
- *
- * @link http://php-di.org/
- * @copyright Matthieu Napoli (http://mnapoli.fr/)
- * @license http://www.opensource.org/licenses/mit-license.php MIT (see the LICENSE file)
- */
-
-namespace DI\Definition;
-
-/**
- * Factory that decorates a sub-definition.
- *
- * @since 5.0
- * @author Matthieu Napoli <matthieu@mnapoli.fr>
- */
-class DecoratorDefinition extends FactoryDefinition implements Definition, HasSubDefinition
-{
- /**
- * @var Definition
- */
- private $decorated;
-
- /**
- * @return string
- */
- public function getSubDefinitionName()
- {
- return $this->getName();
- }
-
- /**
- * @param Definition $definition
- */
- public function setSubDefinition(Definition $definition)
- {
- $this->decorated = $definition;
- }
-
- /**
- * @return Definition
- */
- public function getDecoratedDefinition()
- {
- return $this->decorated;
- }
-}
+++ /dev/null
-<?php
-/**
- * PHP-DI
- *
- * @link http://php-di.org/
- * @copyright Matthieu Napoli (http://mnapoli.fr/)
- * @license http://www.opensource.org/licenses/mit-license.php MIT (see the LICENSE file)
- */
-
-namespace DI\Definition;
-
-/**
- * Definition
- *
- * @author Matthieu Napoli <matthieu@mnapoli.fr>
- */
-interface Definition
-{
- /**
- * Returns the name of the entry in the container
- *
- * @return string
- */
- public function getName();
-
- /**
- * Returns the scope of the entry
- *
- * @return string
- */
- public function getScope();
-}
+++ /dev/null
-<?php
-/**
- * PHP-DI
- *
- * @link http://php-di.org/
- * @copyright Matthieu Napoli (http://mnapoli.fr/)
- * @license http://www.opensource.org/licenses/mit-license.php MIT (see the LICENSE file)
- */
-
-namespace DI\Definition\Dumper;
-
-use DI\Definition\AliasDefinition;
-use DI\Definition\Definition;
-
-/**
- * Dumps alias definitions.
- *
- * @since 4.1
- * @author Matthieu Napoli <matthieu@mnapoli.fr>
- */
-class AliasDefinitionDumper implements DefinitionDumper
-{
- /**
- * {@inheritdoc}
- */
- public function dump(Definition $definition)
- {
- if (! $definition instanceof AliasDefinition) {
- throw new \InvalidArgumentException(sprintf(
- 'This definition dumper is only compatible with AliasDefinition objects, %s given',
- get_class($definition)
- ));
- }
-
- if ($definition->getName()) {
- return sprintf(
- "get(%s => %s)",
- $definition->getName(),
- $definition->getTargetEntryName()
- );
- }
-
- return sprintf(
- "get(%s)",
- $definition->getTargetEntryName()
- );
- }
-}
+++ /dev/null
-<?php
-/**
- * PHP-DI
- *
- * @link http://php-di.org/
- * @copyright Matthieu Napoli (http://mnapoli.fr/)
- * @license http://www.opensource.org/licenses/mit-license.php MIT (see the LICENSE file)
- */
-
-namespace DI\Definition\Dumper;
-
-use DI\Debug;
-use DI\Definition\ArrayDefinition;
-use DI\Definition\Definition;
-use DI\Definition\Helper\DefinitionHelper;
-
-/**
- * Dumps array definitions.
- *
- * @since 5.0
- * @author Matthieu Napoli <matthieu@mnapoli.fr>
- */
-class ArrayDefinitionDumper implements DefinitionDumper
-{
- /**
- * {@inheritdoc}
- */
- public function dump(Definition $definition)
- {
- if (! $definition instanceof ArrayDefinition) {
- throw new \InvalidArgumentException(sprintf(
- 'This definition dumper is only compatible with ArrayDefinition objects, %s given',
- get_class($definition)
- ));
- }
-
- $str = '[' . PHP_EOL;
-
- foreach ($definition->getValues() as $key => $value) {
- if (is_string($key)) {
- $key = "'" . $key . "'";
- }
-
- $str .= ' ' . $key . ' => ';
-
- if ($value instanceof DefinitionHelper) {
- $nestedDefinition = Debug::dumpDefinition($value->getDefinition(''));
- $str .= $this->indent($nestedDefinition);
- } else {
- $str .= var_export($value, true);
- }
-
- $str .= ',' . PHP_EOL;
- }
-
- $str .= ']';
-
- return $str;
- }
-
- private function indent($str)
- {
- return str_replace(PHP_EOL, PHP_EOL . " ", $str);
- }
-}
+++ /dev/null
-<?php
-/**
- * PHP-DI
- *
- * @link http://php-di.org/
- * @copyright Matthieu Napoli (http://mnapoli.fr/)
- * @license http://www.opensource.org/licenses/mit-license.php MIT (see the LICENSE file)
- */
-
-namespace DI\Definition\Dumper;
-
-use DI\Definition\DecoratorDefinition;
-use DI\Definition\Definition;
-
-/**
- * Dumps decorator definitions.
- *
- * @since 5.0
- * @author Matthieu Napoli <matthieu@mnapoli.fr>
- */
-class DecoratorDefinitionDumper implements DefinitionDumper
-{
- /**
- * {@inheritdoc}
- */
- public function dump(Definition $definition)
- {
- if (! $definition instanceof DecoratorDefinition) {
- throw new \InvalidArgumentException(sprintf(
- 'This definition dumper is only compatible with DecoratorDefinition objects, %s given',
- get_class($definition)
- ));
- }
-
- return 'Decorate(' . $definition->getSubDefinitionName() . ')';
- }
-}
+++ /dev/null
-<?php
-/**
- * PHP-DI
- *
- * @link http://php-di.org/
- * @copyright Matthieu Napoli (http://mnapoli.fr/)
- * @license http://www.opensource.org/licenses/mit-license.php MIT (see the LICENSE file)
- */
-
-namespace DI\Definition\Dumper;
-
-use DI\Definition\Definition;
-
-/**
- * Dumps definitions to help debugging.
- *
- * @since 4.1
- * @author Matthieu Napoli <matthieu@mnapoli.fr>
- */
-interface DefinitionDumper
-{
- /**
- * Returns the given definition as string representation.
- *
- * @param Definition $definition
- *
- * @return string
- */
- public function dump(Definition $definition);
-}
+++ /dev/null
-<?php
-/**
- * PHP-DI
- *
- * @link http://php-di.org/
- * @copyright Matthieu Napoli (http://mnapoli.fr/)
- * @license http://www.opensource.org/licenses/mit-license.php MIT (see the LICENSE file)
- */
-
-namespace DI\Definition\Dumper;
-
-use DI\Definition\Definition;
-
-/**
- * Dispatch a definition to the appropriate dumper.
- *
- * @since 4.1
- * @author Matthieu Napoli <matthieu@mnapoli.fr>
- */
-class DefinitionDumperDispatcher implements DefinitionDumper
-{
- /**
- * Definition dumpers, indexed by the class of the definition they can dump.
- *
- * @var DefinitionDumper[]|null
- */
- private $dumpers = [];
-
- public function __construct($dumpers = null)
- {
- $this->dumpers = $dumpers;
- }
-
- /**
- * {@inheritdoc}
- */
- public function dump(Definition $definition)
- {
- $this->initialize();
-
- $class = get_class($definition);
-
- if (! array_key_exists($class, $this->dumpers)) {
- throw new \RuntimeException(sprintf(
- 'There is no DefinitionDumper capable of dumping this definition of type %s',
- $class
- ));
- }
-
- $dumper = $this->dumpers[$class];
-
- return $dumper->dump($definition);
- }
-
- private function initialize()
- {
- if ($this->dumpers === null) {
- $this->dumpers = [
- 'DI\Definition\ValueDefinition' => new ValueDefinitionDumper(),
- 'DI\Definition\FactoryDefinition' => new FactoryDefinitionDumper(),
- 'DI\Definition\DecoratorDefinition' => new DecoratorDefinitionDumper(),
- 'DI\Definition\AliasDefinition' => new AliasDefinitionDumper(),
- 'DI\Definition\ObjectDefinition' => new ObjectDefinitionDumper(),
- 'DI\Definition\EnvironmentVariableDefinition' => new EnvironmentVariableDefinitionDumper(),
- ];
- }
- }
-}
+++ /dev/null
-<?php
-/**
- * PHP-DI
- *
- * @link http://php-di.org/
- * @copyright Matthieu Napoli (http://mnapoli.fr/)
- * @license http://www.opensource.org/licenses/mit-license.php MIT (see the LICENSE file)
- */
-
-namespace DI\Definition\Dumper;
-
-use DI\Debug;
-use DI\Definition\Definition;
-use DI\Definition\EntryReference;
-use DI\Definition\EnvironmentVariableDefinition;
-use DI\Definition\Helper\DefinitionHelper;
-
-/**
- * Dumps environment variable definitions.
- *
- * @author James Harris <james.harris@icecave.com.au>
- */
-class EnvironmentVariableDefinitionDumper implements DefinitionDumper
-{
- /**
- * {@inheritdoc}
- */
- public function dump(Definition $definition)
- {
- if (! $definition instanceof EnvironmentVariableDefinition) {
- throw new \InvalidArgumentException(sprintf(
- 'This definition dumper is only compatible with EnvironmentVariableDefinition objects, %s given',
- get_class($definition)
- ));
- }
-
- $str = " variable = " . $definition->getVariableName();
- $str .= PHP_EOL . " optional = " . ($definition->isOptional() ? 'yes' : 'no');
-
- if ($definition->isOptional()) {
- $defaultValue = $definition->getDefaultValue();
-
- if ($defaultValue instanceof DefinitionHelper) {
- $nestedDefinition = Debug::dumpDefinition($defaultValue->getDefinition(''));
- $defaultValueStr = $this->indent($nestedDefinition);
- } else {
- $defaultValueStr = var_export($defaultValue, true);
- }
-
- $str .= PHP_EOL . " default = " . $defaultValueStr;
- }
-
- return sprintf(
- "Environment variable (" . PHP_EOL . "%s" . PHP_EOL . ")",
- $str
- );
- }
-
- private function indent($str)
- {
- return str_replace(PHP_EOL, PHP_EOL . " ", $str);
- }
-}
+++ /dev/null
-<?php
-/**
- * PHP-DI
- *
- * @link http://php-di.org/
- * @copyright Matthieu Napoli (http://mnapoli.fr/)
- * @license http://www.opensource.org/licenses/mit-license.php MIT (see the LICENSE file)
- */
-
-namespace DI\Definition\Dumper;
-
-use DI\Definition\Definition;
-use DI\Definition\FactoryDefinition;
-
-/**
- * Dumps factory definitions.
- *
- * @since 4.1
- * @author Matthieu Napoli <matthieu@mnapoli.fr>
- */
-class FactoryDefinitionDumper implements DefinitionDumper
-{
- /**
- * {@inheritdoc}
- */
- public function dump(Definition $definition)
- {
- if (! $definition instanceof FactoryDefinition) {
- throw new \InvalidArgumentException(sprintf(
- 'This definition dumper is only compatible with FactoryDefinition objects, %s given',
- get_class($definition)
- ));
- }
-
- return 'Factory';
- }
-}
+++ /dev/null
-<?php
-/**
- * PHP-DI
- *
- * @link http://php-di.org/
- * @copyright Matthieu Napoli (http://mnapoli.fr/)
- * @license http://www.opensource.org/licenses/mit-license.php MIT (see the LICENSE file)
- */
-
-namespace DI\Definition\Dumper;
-
-use DI\Definition\ObjectDefinition;
-use DI\Definition\ObjectDefinition\MethodInjection;
-use DI\Definition\Definition;
-use DI\Definition\EntryReference;
-use ReflectionException;
-use ReflectionMethod;
-
-/**
- * Dumps object definitions.
- *
- * @since 4.1
- * @author Matthieu Napoli <matthieu@mnapoli.fr>
- */
-class ObjectDefinitionDumper implements DefinitionDumper
-{
- /**
- * {@inheritdoc}
- */
- public function dump(Definition $definition)
- {
- if (! $definition instanceof ObjectDefinition) {
- throw new \InvalidArgumentException(sprintf(
- 'This definition dumper is only compatible with ObjectDefinition objects, %s given',
- get_class($definition)
- ));
- }
-
- $className = $definition->getClassName();
- $classExist = class_exists($className) || interface_exists($className);
-
- // Class
- if (! $classExist) {
- $warning = '#UNKNOWN# ';
- } else {
- $class = new \ReflectionClass($className);
- $warning = $class->isInstantiable() ? '' : '#NOT INSTANTIABLE# ';
- }
- $str = sprintf(' class = %s%s', $warning, $className);
-
- // Scope
- $str .= PHP_EOL . " scope = " . $definition->getScope();
-
- // Lazy
- $str .= PHP_EOL . " lazy = " . var_export($definition->isLazy(), true);
-
- if ($classExist) {
- // Constructor
- $str .= $this->dumpConstructor($className, $definition);
-
- // Properties
- $str .= $this->dumpProperties($definition);
-
- // Methods
- $str .= $this->dumpMethods($className, $definition);
- }
-
- return sprintf("Object (" . PHP_EOL . "%s" . PHP_EOL . ")", $str);
- }
-
- private function dumpConstructor($className, ObjectDefinition $definition)
- {
- $str = '';
-
- $constructorInjection = $definition->getConstructorInjection();
-
- if ($constructorInjection !== null) {
- $parameters = $this->dumpMethodParameters($className, $constructorInjection);
-
- $str .= sprintf(PHP_EOL . " __construct(" . PHP_EOL . " %s" . PHP_EOL . " )", $parameters);
- }
-
- return $str;
- }
-
- private function dumpProperties(ObjectDefinition $definition)
- {
- $str = '';
-
- foreach ($definition->getPropertyInjections() as $propertyInjection) {
- $value = $propertyInjection->getValue();
- if ($value instanceof EntryReference) {
- $valueStr = sprintf('get(%s)', $value->getName());
- } else {
- $valueStr = var_export($value, true);
- }
-
- $str .= sprintf(PHP_EOL . " $%s = %s", $propertyInjection->getPropertyName(), $valueStr);
- }
-
- return $str;
- }
-
- private function dumpMethods($className, ObjectDefinition $definition)
- {
- $str = '';
-
- foreach ($definition->getMethodInjections() as $methodInjection) {
- $parameters = $this->dumpMethodParameters($className, $methodInjection);
-
- $str .= sprintf(PHP_EOL . " %s(" . PHP_EOL . " %s" . PHP_EOL . " )", $methodInjection->getMethodName(), $parameters);
- }
-
- return $str;
- }
-
- private function dumpMethodParameters($className, MethodInjection $methodInjection)
- {
- $methodReflection = new \ReflectionMethod($className, $methodInjection->getMethodName());
-
- $args = [];
-
- $definitionParameters = $methodInjection->getParameters();
-
- foreach ($methodReflection->getParameters() as $index => $parameter) {
- if (array_key_exists($index, $definitionParameters)) {
- $value = $definitionParameters[$index];
-
- if ($value instanceof EntryReference) {
- $args[] = sprintf('$%s = get(%s)', $parameter->getName(), $value->getName());
- } else {
- $args[] = sprintf('$%s = %s', $parameter->getName(), var_export($value, true));
- }
- continue;
- }
-
- // If the parameter is optional and wasn't specified, we take its default value
- if ($parameter->isOptional()) {
- try {
- $value = $parameter->getDefaultValue();
-
- $args[] = sprintf(
- '$%s = (default value) %s',
- $parameter->getName(),
- var_export($value, true)
- );
- continue;
- } catch (ReflectionException $e) {
- // The default value can't be read through Reflection because it is a PHP internal class
- }
- }
-
- $args[] = sprintf('$%s = #UNDEFINED#', $parameter->getName());
- }
-
- return implode(PHP_EOL . ' ', $args);
- }
-}
+++ /dev/null
-<?php
-/**
- * PHP-DI
- *
- * @link http://php-di.org/
- * @copyright Matthieu Napoli (http://mnapoli.fr/)
- * @license http://www.opensource.org/licenses/mit-license.php MIT (see the LICENSE file)
- */
-
-namespace DI\Definition\Dumper;
-
-use DI\Definition\Definition;
-use DI\Definition\StringDefinition;
-
-/**
- * Dumps string definitions.
- *
- * @since 5.0
- * @author Matthieu Napoli <matthieu@mnapoli.fr>
- */
-class StringDefinitionDumper implements DefinitionDumper
-{
- /**
- * {@inheritdoc}
- */
- public function dump(Definition $definition)
- {
- if (! $definition instanceof StringDefinition) {
- throw new \InvalidArgumentException(sprintf(
- 'This definition dumper is only compatible with StringDefinition objects, %s given',
- get_class($definition)
- ));
- }
-
- return $definition->getExpression();
- }
-}
+++ /dev/null
-<?php
-/**
- * PHP-DI
- *
- * @link http://php-di.org/
- * @copyright Matthieu Napoli (http://mnapoli.fr/)
- * @license http://www.opensource.org/licenses/mit-license.php MIT (see the LICENSE file)
- */
-
-namespace DI\Definition\Dumper;
-
-use DI\Definition\Definition;
-use DI\Definition\ValueDefinition;
-
-/**
- * Dumps value definitions.
- *
- * @since 4.1
- * @author Matthieu Napoli <matthieu@mnapoli.fr>
- */
-class ValueDefinitionDumper implements DefinitionDumper
-{
- /**
- * {@inheritdoc}
- */
- public function dump(Definition $definition)
- {
- if (! $definition instanceof ValueDefinition) {
- throw new \InvalidArgumentException(sprintf(
- 'This definition dumper is only compatible with ValueDefinition objects, %s given',
- get_class($definition)
- ));
- }
-
- ob_start();
-
- var_dump($definition->getValue());
-
- return sprintf(
- "Value (" . PHP_EOL . " %s" . PHP_EOL . ")",
- trim(ob_get_clean())
- );
- }
-}
+++ /dev/null
-<?php
-/**
- * PHP-DI
- *
- * @link http://php-di.org/
- * @copyright Matthieu Napoli (http://mnapoli.fr/)
- * @license http://www.opensource.org/licenses/mit-license.php MIT (see the LICENSE file)
- */
-
-namespace DI\Definition;
-
-use DI\Definition\Helper\DefinitionHelper;
-
-/**
- * Represents a reference to a container entry.
- *
- * TODO should EntryReference and AliasDefinition be merged into a ReferenceDefinition?
- *
- * @author Matthieu Napoli <matthieu@mnapoli.fr>
- */
-class EntryReference implements DefinitionHelper
-{
- /**
- * Entry name
- * @var string
- */
- private $name;
-
- /**
- * @param string $entryName Entry name
- */
- public function __construct($entryName)
- {
- $this->name = $entryName;
- }
-
- /**
- * @return string Entry name
- */
- public function getName()
- {
- return $this->name;
- }
-
- /**
- * {@inheritdoc}
- */
- public function getDefinition($entryName)
- {
- return new AliasDefinition($entryName, $this->name);
- }
-}
+++ /dev/null
-<?php
-/**
- * PHP-DI
- *
- * @link http://php-di.org/
- * @copyright Matthieu Napoli (http://mnapoli.fr/)
- * @license http://www.opensource.org/licenses/mit-license.php MIT (see the LICENSE file)
- */
-
-namespace DI\Definition;
-
-use DI\Scope;
-
-/**
- * Defines a reference to an environment variable, with fallback to a default
- * value if the environment variable is not defined.
- *
- * @author James Harris <james.harris@icecave.com.au>
- */
-class EnvironmentVariableDefinition implements CacheableDefinition
-{
- /**
- * Entry name
- * @var string
- */
- private $name;
-
- /**
- * The name of the environment variable
- * @var string
- */
- private $variableName;
-
- /**
- * Whether or not the environment variable definition is optional
- *
- * If true and the environment variable given by $variableName has not been
- * defined, $defaultValue is used.
- *
- * @var boolean
- */
- private $isOptional;
-
- /**
- * The default value to use if the environment variable is optional and not provided
- * @var mixed
- */
- private $defaultValue;
-
- /**
- * @var string|null
- */
- private $scope;
-
- /**
- * @param string $name Entry name
- * @param string $variableName The name of the environment variable
- * @param boolean $isOptional Whether or not the environment variable definition is optional
- * @param mixed $defaultValue The default value to use if the environment variable is optional and not provided
- */
- public function __construct($name, $variableName, $isOptional = false, $defaultValue = null)
- {
- $this->name = $name;
- $this->variableName = $variableName;
- $this->isOptional = $isOptional;
- $this->defaultValue = $defaultValue;
- }
-
- /**
- * @return string Entry name
- */
- public function getName()
- {
- return $this->name;
- }
-
- /**
- * @return string The name of the environment variable
- */
- public function getVariableName()
- {
- return $this->variableName;
- }
-
- /**
- * @return boolean Whether or not the environment variable definition is optional
- */
- public function isOptional()
- {
- return $this->isOptional;
- }
-
- /**
- * @return mixed The default value to use if the environment variable is optional and not provided
- */
- public function getDefaultValue()
- {
- return $this->defaultValue;
- }
-
- /**
- * @param string $scope
- */
- public function setScope($scope)
- {
- $this->scope = $scope;
- }
-
- /**
- * {@inheritdoc}
- */
- public function getScope()
- {
- return $this->scope ?: Scope::SINGLETON;
- }
-}
+++ /dev/null
-<?php
-/**
- * PHP-DI
- *
- * @link http://php-di.org/
- * @copyright Matthieu Napoli (http://mnapoli.fr/)
- * @license http://www.opensource.org/licenses/mit-license.php MIT (see the LICENSE file)
- */
-
-namespace DI\Definition\Exception;
-
-/**
- * Exception in the definitions using annotations
- *
- * @author Matthieu Napoli <matthieu@mnapoli.fr>
- */
-class AnnotationException extends DefinitionException
-{
-}
+++ /dev/null
-<?php
-/**
- * PHP-DI
- *
- * @link http://php-di.org/
- * @copyright Matthieu Napoli (http://mnapoli.fr/)
- * @license http://www.opensource.org/licenses/mit-license.php MIT (see the LICENSE file)
- */
-
-namespace DI\Definition\Exception;
-
-use DI\Debug;
-use DI\Definition\Definition;
-
-/**
- * Invalid DI definitions
- *
- * @author Matthieu Napoli <matthieu@mnapoli.fr>
- */
-class DefinitionException extends \Exception
-{
- public static function create(Definition $definition, $message)
- {
- return new self(sprintf(
- "%s" . PHP_EOL . "Full definition:" . PHP_EOL . "%s",
- $message,
- Debug::dumpDefinition($definition)
- ));
- }
-}
+++ /dev/null
-<?php
-/**
- * PHP-DI
- *
- * @link http://php-di.org/
- * @copyright Matthieu Napoli (http://mnapoli.fr/)
- * @license http://www.opensource.org/licenses/mit-license.php MIT (see the LICENSE file)
- */
-
-namespace DI\Definition;
-
-use DI\Scope;
-
-/**
- * Definition of a value or class with a factory.
- *
- * @author Matthieu Napoli <matthieu@mnapoli.fr>
- */
-class FactoryDefinition implements Definition
-{
- /**
- * Entry name.
- * @var string
- */
- private $name;
-
- /**
- * @var string
- */
- private $scope;
-
- /**
- * Callable that returns the value.
- * @var callable
- */
- private $factory;
-
- /**
- * @param string $name Entry name
- * @param callable $factory Callable that returns the value associated to the entry name.
- * @param string|null $scope
- */
- public function __construct($name, $factory, $scope = null)
- {
- $this->name = $name;
- $this->factory = $factory;
- $this->scope = $scope;
- }
-
- /**
- * @return string Entry name.
- */
- public function getName()
- {
- return $this->name;
- }
-
- /**
- * Default scope is singleton: the callable is called once and the result is shared.
- *
- * {@inheritdoc}
- */
- public function getScope()
- {
- return $this->scope ?: Scope::SINGLETON;
- }
-
- /**
- * @return callable Callable that returns the value associated to the entry name.
- */
- public function getCallable()
- {
- return $this->factory;
- }
-}
+++ /dev/null
-<?php
-/**
- * PHP-DI
- *
- * @link http://php-di.org/
- * @copyright Matthieu Napoli (http://mnapoli.fr/)
- * @license http://www.opensource.org/licenses/mit-license.php MIT (see the LICENSE file)
- */
-
-namespace DI\Definition;
-
-/**
- * A definition that has a sub-definition.
- *
- * @author Matthieu Napoli <matthieu@mnapoli.fr>
- */
-interface HasSubDefinition extends Definition
-{
- /**
- * @return string
- */
- public function getSubDefinitionName();
-
- /**
- * @param Definition $definition
- */
- public function setSubDefinition(Definition $definition);
-}
+++ /dev/null
-<?php
-/**
- * PHP-DI
- *
- * @link http://php-di.org/
- * @copyright Matthieu Napoli (http://mnapoli.fr/)
- * @license http://www.opensource.org/licenses/mit-license.php MIT (see the LICENSE file)
- */
-
-namespace DI\Definition\Helper;
-
-use DI\Definition\ArrayDefinitionExtension;
-
-/**
- * Helps extending the definition of an array.
- *
- * For example you can add new entries to the array.
- *
- * @since 5.0
- * @author Matthieu Napoli <matthieu@mnapoli.fr>
- */
-class ArrayDefinitionExtensionHelper implements DefinitionHelper
-{
- /**
- * @var array
- */
- private $values = [];
-
- /**
- * @param array $values Values to add to the array.
- */
- public function __construct(array $values)
- {
- $this->values = $values;
- }
-
- /**
- * @param string $entryName Container entry name
- *
- * @return ArrayDefinitionExtension
- */
- public function getDefinition($entryName)
- {
- return new ArrayDefinitionExtension($entryName, $this->values);
- }
-}
+++ /dev/null
-<?php
-/**
- * PHP-DI
- *
- * @link http://php-di.org/
- * @copyright Matthieu Napoli (http://mnapoli.fr/)
- * @license http://www.opensource.org/licenses/mit-license.php MIT (see the LICENSE file)
- */
-
-namespace DI\Definition\Helper;
-
-/**
- * Helps defining container entries.
- *
- * @author Matthieu Napoli <matthieu@mnapoli.fr>
- */
-interface DefinitionHelper
-{
- /**
- * @param string $entryName Container entry name
- * @return \DI\Definition\Definition
- */
- public function getDefinition($entryName);
-}
+++ /dev/null
-<?php
-/**
- * PHP-DI
- *
- * @link http://php-di.org/
- * @copyright Matthieu Napoli (http://mnapoli.fr/)
- * @license http://www.opensource.org/licenses/mit-license.php MIT (see the LICENSE file)
- */
-
-namespace DI\Definition\Helper;
-
-use DI\Definition\EnvironmentVariableDefinition;
-
-/**
- * Helps defining how to create an instance of an environment variable definition.
- *
- * @author James Harris <james.harris@icecave.com.au>
- */
-class EnvironmentVariableDefinitionHelper implements DefinitionHelper
-{
- /**
- * The name of the environment variable
- * @var string
- */
- private $variableName;
-
- /**
- * Whether or not the environment variable definition is optional
- *
- * If true and the environment variable given by $variableName has not been
- * defined, $defaultValue is used.
- *
- * @var boolean
- */
- private $isOptional;
-
- /**
- * The default value to use if the environment variable is optional and not provided
- * @var mixed
- */
- private $defaultValue;
-
- /**
- * @param string $variableName The name of the environment variable
- * @param boolean $isOptional Whether or not the environment variable definition is optional
- * @param mixed $defaultValue The default value to use if the environment variable is optional and not provided
- */
- public function __construct($variableName, $isOptional, $defaultValue = null)
- {
- $this->variableName = $variableName;
- $this->isOptional = $isOptional;
- $this->defaultValue = $defaultValue;
- }
-
- /**
- * @param string $entryName Container entry name
- *
- * @return EnvironmentVariableDefinition
- */
- public function getDefinition($entryName)
- {
- return new EnvironmentVariableDefinition($entryName, $this->variableName, $this->isOptional, $this->defaultValue);
- }
-}
+++ /dev/null
-<?php
-/**
- * PHP-DI
- *
- * @link http://php-di.org/
- * @copyright Matthieu Napoli (http://mnapoli.fr/)
- * @license http://www.opensource.org/licenses/mit-license.php MIT (see the LICENSE file)
- */
-
-namespace DI\Definition\Helper;
-
-use DI\Definition\DecoratorDefinition;
-use DI\Definition\FactoryDefinition;
-
-/**
- * Helps defining how to create an instance of a class using a factory (callable).
- *
- * @author Matthieu Napoli <matthieu@mnapoli.fr>
- */
-class FactoryDefinitionHelper implements DefinitionHelper
-{
- /**
- * @var callable
- */
- private $factory;
-
- /**
- * @var string|null
- */
- private $scope;
-
- /**
- * @var bool
- */
- private $decorate;
-
- /**
- * @param callable $factory
- * @param bool $decorate Is the factory decorating a previous definition?
- */
- public function __construct($factory, $decorate = false)
- {
- $this->factory = $factory;
- $this->decorate = $decorate;
- }
-
- /**
- * Defines the scope of the entry.
- *
- * @param string $scope
- *
- * @return FactoryDefinitionHelper
- */
- public function scope($scope)
- {
- $this->scope = $scope;
- return $this;
- }
-
- /**
- * @param string $entryName Container entry name
- * @return FactoryDefinition
- */
- public function getDefinition($entryName)
- {
- if ($this->decorate) {
- return new DecoratorDefinition($entryName, $this->factory, $this->scope);
- }
-
- return new FactoryDefinition($entryName, $this->factory, $this->scope);
- }
-}
+++ /dev/null
-<?php
-/**
- * PHP-DI
- *
- * @link http://php-di.org/
- * @copyright Matthieu Napoli (http://mnapoli.fr/)
- * @license http://www.opensource.org/licenses/mit-license.php MIT (see the LICENSE file)
- */
-
-namespace DI\Definition\Helper;
-
-use DI\Definition\ObjectDefinition;
-use DI\Definition\ObjectDefinition\MethodInjection;
-use DI\Definition\ObjectDefinition\PropertyInjection;
-use DI\Definition\Exception\DefinitionException;
-
-/**
- * Helps defining how to create an instance of a class.
- *
- * @author Matthieu Napoli <matthieu@mnapoli.fr>
- */
-class ObjectDefinitionHelper implements DefinitionHelper
-{
- /**
- * @var string|null
- */
- private $className;
-
- /**
- * @var boolean|null
- */
- private $lazy;
-
- /**
- * @var string|null
- */
- private $scope;
-
- /**
- * Array of constructor parameters.
- * @var array
- */
- private $constructor = [];
-
- /**
- * Array of properties and their value.
- * @var array
- */
- private $properties = [];
-
- /**
- * Array of methods and their parameters.
- * @var array
- */
- private $methods = [];
-
- /**
- * Helper for defining an object.
- *
- * @param string|null $className Class name of the object.
- * If null, the name of the entry (in the container) will be used as class name.
- */
- public function __construct($className = null)
- {
- $this->className = $className;
- }
-
- /**
- * Define the entry as lazy.
- *
- * A lazy entry is created only when it is used, a proxy is injected instead.
- *
- * @return ObjectDefinitionHelper
- */
- public function lazy()
- {
- $this->lazy = true;
- return $this;
- }
-
- /**
- * Defines the scope of the entry.
- *
- * @param string $scope
- *
- * @return ObjectDefinitionHelper
- */
- public function scope($scope)
- {
- $this->scope = $scope;
- return $this;
- }
-
- /**
- * Defines the arguments to use to call the constructor.
- *
- * This method takes a variable number of arguments, example:
- * ->constructor($param1, $param2, $param3)
- *
- * @param mixed ... Parameters to use for calling the constructor of the class.
- *
- * @return ObjectDefinitionHelper
- */
- public function constructor()
- {
- $this->constructor = func_get_args();
- return $this;
- }
-
- /**
- * Defines a value for a specific argument of the constructor.
- *
- * This method is usually used together with annotations or autowiring, when a parameter
- * is not (or cannot be) type-hinted. Using this method instead of constructor() allows to
- * avoid defining all the parameters (letting them being resolved using annotations or autowiring)
- * and only define one.
- *
- * @param string $parameter Parameter for which the value will be given.
- * @param mixed $value Value to give to this parameter.
- *
- * @return ObjectDefinitionHelper
- */
- public function constructorParameter($parameter, $value)
- {
- $this->constructor[$parameter] = $value;
- return $this;
- }
-
- /**
- * Defines a value to inject in a property of the object.
- *
- * @param string $property Entry in which to inject the value.
- * @param mixed $value Value to inject in the property.
- *
- * @return ObjectDefinitionHelper
- */
- public function property($property, $value)
- {
- $this->properties[$property] = $value;
- return $this;
- }
-
- /**
- * Defines a method to call and the arguments to use.
- *
- * This method takes a variable number of arguments after the method name, example:
- *
- * ->method('myMethod', $param1, $param2)
- *
- * Can be used multiple times to declare multiple calls.
- *
- * @param string $method Name of the method to call.
- * @param mixed ... Parameters to use for calling the method.
- *
- * @return ObjectDefinitionHelper
- */
- public function method($method)
- {
- $args = func_get_args();
- array_shift($args);
-
- if (! isset($this->methods[$method])) {
- $this->methods[$method] = [];
- }
-
- $this->methods[$method][] = $args;
-
- return $this;
- }
-
- /**
- * Defines a method to call and a value for a specific argument.
- *
- * This method is usually used together with annotations or autowiring, when a parameter
- * is not (or cannot be) type-hinted. Using this method instead of method() allows to
- * avoid defining all the parameters (letting them being resolved using annotations or
- * autowiring) and only define one.
- *
- * If multiple calls to the method have been configured already (e.g. in a previous definition)
- * then this method only overrides the parameter for the *first* call.
- *
- * @param string $method Name of the method to call.
- * @param string $parameter Name or index of the parameter for which the value will be given.
- * @param mixed $value Value to give to this parameter.
- *
- * @return ObjectDefinitionHelper
- */
- public function methodParameter($method, $parameter, $value)
- {
- // Special case for the constructor
- if ($method === '__construct') {
- $this->constructor[$parameter] = $value;
- return $this;
- }
-
- if (! isset($this->methods[$method])) {
- $this->methods[$method] = [0 => []];
- }
-
- $this->methods[$method][0][$parameter] = $value;
-
- return $this;
- }
-
- /**
- * {@inheritdoc}
- */
- public function getDefinition($entryName)
- {
- $definition = new ObjectDefinition($entryName, $this->className);
-
- if ($this->lazy !== null) {
- $definition->setLazy($this->lazy);
- }
- if ($this->scope !== null) {
- $definition->setScope($this->scope);
- }
-
- if (! empty($this->constructor)) {
- $parameters = $this->fixParameters($definition, '__construct', $this->constructor);
- $constructorInjection = MethodInjection::constructor($parameters);
- $definition->setConstructorInjection($constructorInjection);
- }
-
- if (! empty($this->properties)) {
- foreach ($this->properties as $property => $value) {
- $definition->addPropertyInjection(
- new PropertyInjection($property, $value)
- );
- }
- }
-
- if (! empty($this->methods)) {
- foreach ($this->methods as $method => $calls) {
- foreach ($calls as $parameters) {
- $parameters = $this->fixParameters($definition, $method, $parameters);
- $methodInjection = new MethodInjection($method, $parameters);
- $definition->addMethodInjection($methodInjection);
- }
- }
- }
-
- return $definition;
- }
-
- /**
- * Fixes parameters indexed by the parameter name -> reindex by position.
- *
- * This is necessary so that merging definitions between sources is possible.
- *
- * @param ObjectDefinition $definition
- * @param string $method
- * @param array $parameters
- * @throws DefinitionException
- * @return array
- */
- private function fixParameters(ObjectDefinition $definition, $method, $parameters)
- {
- $fixedParameters = [];
-
- foreach ($parameters as $index => $parameter) {
- // Parameter indexed by the parameter name, we reindex it with its position
- if (is_string($index)) {
- $callable = [$definition->getClassName(), $method];
- try {
- $reflectionParameter = new \ReflectionParameter($callable, $index);
- } catch (\ReflectionException $e) {
- throw DefinitionException::create($definition, "Parameter with name '$index' could not be found");
- }
-
- $index = $reflectionParameter->getPosition();
- }
-
- $fixedParameters[$index] = $parameter;
- }
-
- return $fixedParameters;
- }
-}
+++ /dev/null
-<?php
-/**
- * PHP-DI
- *
- * @link http://php-di.org/
- * @copyright Matthieu Napoli (http://mnapoli.fr/)
- * @license http://www.opensource.org/licenses/mit-license.php MIT (see the LICENSE file)
- */
-
-namespace DI\Definition\Helper;
-
-use DI\Definition\StringDefinition;
-
-/**
- * @since 5.0
- * @author Matthieu Napoli <matthieu@mnapoli.fr>
- */
-class StringDefinitionHelper implements DefinitionHelper
-{
- /**
- * @var string
- */
- private $expression;
-
- public function __construct($expression)
- {
- $this->expression = $expression;
- }
-
- /**
- * @param string $entryName Container entry name
- *
- * @return StringDefinition
- */
- public function getDefinition($entryName)
- {
- return new StringDefinition($entryName, $this->expression);
- }
-}
+++ /dev/null
-<?php
-/**
- * PHP-DI
- *
- * @link http://php-di.org/
- * @copyright Matthieu Napoli (http://mnapoli.fr/)
- * @license http://www.opensource.org/licenses/mit-license.php MIT (see the LICENSE file)
- */
-
-namespace DI\Definition\Helper;
-
-use DI\Definition\ValueDefinition;
-
-/**
- * Helps defining a value.
- *
- * @author Matthieu Napoli <matthieu@mnapoli.fr>
- */
-class ValueDefinitionHelper implements DefinitionHelper
-{
- /**
- * @var mixed
- */
- private $value;
-
- /**
- * @param mixed $value
- */
- public function __construct($value)
- {
- $this->value = $value;
- }
-
- /**
- * @param string $entryName Container entry name
- * @return ValueDefinition
- */
- public function getDefinition($entryName)
- {
- return new ValueDefinition($entryName, $this->value);
- }
-}
+++ /dev/null
-<?php
-/**
- * PHP-DI
- *
- * @link http://php-di.org/
- * @copyright Matthieu Napoli (http://mnapoli.fr/)
- * @license http://www.opensource.org/licenses/mit-license.php MIT (see the LICENSE file)
- */
-
-namespace DI\Definition;
-
-use DI\Scope;
-
-/**
- * Defines injections on an existing class instance.
- *
- * @since 5.0
- * @author Matthieu Napoli <matthieu@mnapoli.fr>
- */
-class InstanceDefinition implements Definition
-{
- /**
- * Instance on which to inject dependencies.
- *
- * @var object
- */
- private $instance;
-
- /**
- * @var ObjectDefinition
- */
- private $objectDefinition;
-
- /**
- * @param object $instance
- * @param ObjectDefinition $objectDefinition
- */
- public function __construct($instance, ObjectDefinition $objectDefinition)
- {
- $this->instance = $instance;
- $this->objectDefinition = $objectDefinition;
- }
-
- /**
- * {@inheritdoc}
- */
- public function getName()
- {
- // Name are superfluous for instance definitions
- return '';
- }
-
- /**
- * {@inheritdoc}
- */
- public function getScope()
- {
- return Scope::PROTOTYPE;
- }
-
- /**
- * @return object
- */
- public function getInstance()
- {
- return $this->instance;
- }
-
- /**
- * @return ObjectDefinition
- */
- public function getObjectDefinition()
- {
- return $this->objectDefinition;
- }
-}
+++ /dev/null
-<?php
-/**
- * PHP-DI
- *
- * @link http://php-di.org/
- * @copyright Matthieu Napoli (http://mnapoli.fr/)
- * @license http://www.opensource.org/licenses/mit-license.php MIT (see the LICENSE file)
- */
-
-namespace DI\Definition;
-
-use DI\Definition\ObjectDefinition\MethodInjection;
-use DI\Definition\ObjectDefinition\PropertyInjection;
-use DI\Scope;
-use ReflectionClass;
-
-/**
- * Defines how an object can be instantiated.
- *
- * @author Matthieu Napoli <matthieu@mnapoli.fr>
- */
-class ObjectDefinition implements Definition, CacheableDefinition, HasSubDefinition
-{
- /**
- * Entry name (most of the time, same as $classname)
- * @var string
- */
- private $name;
-
- /**
- * Class name (if null, then the class name is $name)
- * @var string|null
- */
- private $className;
-
- /**
- * Constructor parameter injection
- * @var MethodInjection|null
- */
- private $constructorInjection;
-
- /**
- * Property injections
- * @var PropertyInjection[]
- */
- private $propertyInjections = [];
-
- /**
- * Method calls
- * @var MethodInjection[][]
- */
- private $methodInjections = [];
-
- /**
- * @var string|null
- */
- private $scope;
-
- /**
- * @var boolean|null
- */
- private $lazy;
-
- /**
- * Store if the class exists. Storing it (in cache) avoids recomputing this.
- *
- * @var bool
- */
- private $classExists;
-
- /**
- * Store if the class is instantiable. Storing it (in cache) avoids recomputing this.
- *
- * @var bool
- */
- private $isInstantiable;
-
- /**
- * @param string $name Class name
- * @param string $className
- */
- public function __construct($name, $className = null)
- {
- $this->name = (string) $name;
- $this->setClassName($className);
- }
-
- /**
- * @return string Entry name
- */
- public function getName()
- {
- return $this->name;
- }
-
- /**
- * @param string|null $className
- */
- public function setClassName($className)
- {
- $this->className = $className;
-
- $this->updateCache();
- }
-
- /**
- * @return string Class name
- */
- public function getClassName()
- {
- if ($this->className !== null) {
- return $this->className;
- }
- return $this->name;
- }
-
- /**
- * @return MethodInjection|null
- */
- public function getConstructorInjection()
- {
- return $this->constructorInjection;
- }
-
- /**
- * @param MethodInjection $constructorInjection
- */
- public function setConstructorInjection(MethodInjection $constructorInjection)
- {
- $this->constructorInjection = $constructorInjection;
- }
-
- /**
- * @return PropertyInjection[] Property injections
- */
- public function getPropertyInjections()
- {
- return $this->propertyInjections;
- }
-
- /**
- * @param string $propertyName
- * @return PropertyInjection
- */
- public function getPropertyInjection($propertyName)
- {
- return isset($this->propertyInjections[$propertyName]) ? $this->propertyInjections[$propertyName] : null;
- }
-
- /**
- * @param PropertyInjection $propertyInjection
- */
- public function addPropertyInjection(PropertyInjection $propertyInjection)
- {
- $this->propertyInjections[$propertyInjection->getPropertyName()] = $propertyInjection;
- }
-
- /**
- * @return MethodInjection[] Method injections
- */
- public function getMethodInjections()
- {
- // Return array leafs
- $injections = [];
- array_walk_recursive($this->methodInjections, function ($injection) use (&$injections) {
- $injections[] = $injection;
- });
- return $injections;
- }
-
- /**
- * @param MethodInjection $methodInjection
- */
- public function addMethodInjection(MethodInjection $methodInjection)
- {
- $method = $methodInjection->getMethodName();
- if (! isset($this->methodInjections[$method])) {
- $this->methodInjections[$method] = [];
- }
- $this->methodInjections[$method][] = $methodInjection;
- }
-
- /**
- * @param string $scope
- */
- public function setScope($scope)
- {
- $this->scope = $scope;
- }
-
- /**
- * {@inheritdoc}
- */
- public function getScope()
- {
- return $this->scope ?: Scope::SINGLETON;
- }
-
- /**
- * @param boolean|null $lazy
- */
- public function setLazy($lazy)
- {
- $this->lazy = $lazy;
- }
-
- /**
- * @return bool
- */
- public function isLazy()
- {
- if ($this->lazy !== null) {
- return $this->lazy;
- } else {
- // Default value
- return false;
- }
- }
-
- /**
- * @return bool
- */
- public function classExists()
- {
- return $this->classExists;
- }
-
- /**
- * @return bool
- */
- public function isInstantiable()
- {
- return $this->isInstantiable;
- }
-
- /**
- * {@inheritdoc}
- */
- public function getSubDefinitionName()
- {
- return $this->getClassName();
- }
-
- /**
- * {@inheritdoc}
- */
- public function setSubDefinition(Definition $definition)
- {
- if (! $definition instanceof ObjectDefinition) {
- return;
- }
-
- // The current prevails
- if ($this->className === null) {
- $this->setClassName($definition->className);
- }
- if ($this->scope === null) {
- $this->scope = $definition->scope;
- }
- if ($this->lazy === null) {
- $this->lazy = $definition->lazy;
- }
-
- // Merge constructor injection
- $this->mergeConstructorInjection($definition);
-
- // Merge property injections
- $this->mergePropertyInjections($definition);
-
- // Merge method injections
- $this->mergeMethodInjections($definition);
- }
-
- private function mergeConstructorInjection(ObjectDefinition $definition)
- {
- if ($definition->getConstructorInjection() !== null) {
- if ($this->constructorInjection !== null) {
- // Merge
- $this->constructorInjection->merge($definition->getConstructorInjection());
- } else {
- // Set
- $this->constructorInjection = $definition->getConstructorInjection();
- }
- }
- }
-
- private function mergePropertyInjections(ObjectDefinition $definition)
- {
- foreach ($definition->getPropertyInjections() as $propertyName => $propertyInjection) {
- if (! array_key_exists($propertyName, $this->propertyInjections)) {
- // Add
- $this->propertyInjections[$propertyName] = $propertyInjection;
- }
- }
- }
-
- private function mergeMethodInjections(ObjectDefinition $definition)
- {
- foreach ($definition->methodInjections as $methodName => $calls) {
- if (array_key_exists($methodName, $this->methodInjections)) {
- $this->mergeMethodCalls($calls, $methodName);
- } else {
- // Add
- $this->methodInjections[$methodName] = $calls;
- }
- }
- }
-
- private function mergeMethodCalls(array $calls, $methodName)
- {
- foreach ($calls as $index => $methodInjection) {
- // Merge
- if (array_key_exists($index, $this->methodInjections[$methodName])) {
- // Merge
- $this->methodInjections[$methodName][$index]->merge($methodInjection);
- } else {
- // Add
- $this->methodInjections[$methodName][$index] = $methodInjection;
- }
- }
- }
-
- private function updateCache()
- {
- $className = $this->getClassName();
-
- $this->classExists = class_exists($className) || interface_exists($className);
-
- if (! $this->classExists) {
- $this->isInstantiable = false;
- return;
- }
-
- $class = new ReflectionClass($className);
- $this->isInstantiable = $class->isInstantiable();
- }
-}
+++ /dev/null
-<?php
-/**
- * PHP-DI
- *
- * @link http://php-di.org/
- * @copyright Matthieu Napoli (http://mnapoli.fr/)
- * @license http://www.opensource.org/licenses/mit-license.php MIT (see the LICENSE file)
- */
-
-namespace DI\Definition\ObjectDefinition;
-
-use DI\Definition\Definition;
-use DI\Scope;
-
-/**
- * Describe an injection in an object method.
- *
- * @author Matthieu Napoli <matthieu@mnapoli.fr>
- */
-class MethodInjection implements Definition
-{
- /**
- * @var string
- */
- private $methodName;
-
- /**
- * @var array
- */
- private $parameters = [];
-
- /**
- * @param string $methodName
- * @param array $parameters
- */
- public function __construct($methodName, array $parameters = [])
- {
- $this->methodName = (string) $methodName;
- $this->parameters = $parameters;
- }
-
- public static function constructor(array $parameters = [])
- {
- return new self('__construct', $parameters);
- }
-
- /**
- * @return string Method name
- */
- public function getMethodName()
- {
- return $this->methodName;
- }
-
- /**
- * @return array
- */
- public function getParameters()
- {
- return $this->parameters;
- }
-
- /**
- * Replace the parameters of the definition by a new array of parameters.
- *
- * @param array $parameters
- */
- public function replaceParameters(array $parameters)
- {
- $this->parameters = $parameters;
- }
-
- public function merge(MethodInjection $definition)
- {
- // In case of conflicts, the current definition prevails.
- $this->parameters = $this->parameters + $definition->parameters;
- }
-
- /**
- * {@inheritdoc}
- */
- public function getName()
- {
- return null;
- }
-
- /**
- * {@inheritdoc}
- */
- public function getScope()
- {
- return Scope::PROTOTYPE;
- }
-}
+++ /dev/null
-<?php
-/**
- * PHP-DI
- *
- * @link http://php-di.org/
- * @copyright Matthieu Napoli (http://mnapoli.fr/)
- * @license http://www.opensource.org/licenses/mit-license.php MIT (see the LICENSE file)
- */
-
-namespace DI\Definition\ObjectDefinition;
-
-/**
- * Describe an injection in a class property.
- *
- * @author Matthieu Napoli <matthieu@mnapoli.fr>
- */
-class PropertyInjection
-{
- /**
- * Property name
- * @var string
- */
- private $propertyName;
-
- /**
- * Value that should be injected in the property
- * @var mixed
- */
- private $value;
-
- /**
- * Use for injecting in properties of parent classes: the class name
- * must be the name of the parent class because private properties
- * can be attached to the parent classes, not the one we are resolving.
- * @var string|null
- */
- private $className;
-
- /**
- * @param string $propertyName Property name
- * @param mixed $value Value that should be injected in the property
- * @param string|null $className
- */
- public function __construct($propertyName, $value, $className = null)
- {
- $this->propertyName = (string) $propertyName;
- $this->value = $value;
- $this->className = $className;
- }
-
- /**
- * @return string Property name
- */
- public function getPropertyName()
- {
- return $this->propertyName;
- }
-
- /**
- * @return string Value that should be injected in the property
- */
- public function getValue()
- {
- return $this->value;
- }
-
- /**
- * @return string|null
- */
- public function getClassName()
- {
- return $this->className;
- }
-}
+++ /dev/null
-<?php
-/**
- * PHP-DI
- *
- * @link http://mnapoli.github.com/PHP-DI/
- * @copyright Matthieu Napoli (http://mnapoli.fr/)
- * @license http://www.opensource.org/licenses/mit-license.php MIT (see the LICENSE file)
- */
-
-namespace DI\Definition\Resolver;
-
-use DI\Definition\AliasDefinition;
-use DI\Definition\Definition;
-use Interop\Container\ContainerInterface;
-
-/**
- * Resolves an alias definition to a value.
- *
- * @since 4.0
- * @author Matthieu Napoli <matthieu@mnapoli.fr>
- */
-class AliasResolver implements DefinitionResolver
-{
- /**
- * @var ContainerInterface
- */
- private $container;
-
- /**
- * The resolver needs a container.
- * This container will be used to get the entry to which the alias points to.
- *
- * @param ContainerInterface $container
- */
- public function __construct(ContainerInterface $container)
- {
- $this->container = $container;
- }
-
- /**
- * Resolve an alias definition to a value.
- *
- * This will return the entry the alias points to.
- *
- * @param AliasDefinition $definition
- *
- * {@inheritdoc}
- */
- public function resolve(Definition $definition, array $parameters = [])
- {
- return $this->container->get($definition->getTargetEntryName());
- }
-
- /**
- * @param AliasDefinition $definition
- *
- * {@inheritdoc}
- */
- public function isResolvable(Definition $definition, array $parameters = [])
- {
- return $this->container->has($definition->getTargetEntryName());
- }
-}
+++ /dev/null
-<?php
-/**
- * PHP-DI
- *
- * @link http://mnapoli.github.com/PHP-DI/
- * @copyright Matthieu Napoli (http://mnapoli.fr/)
- * @license http://www.opensource.org/licenses/mit-license.php MIT (see the LICENSE file)
- */
-
-namespace DI\Definition\Resolver;
-
-use DI\Definition\ArrayDefinition;
-use DI\Definition\Definition;
-use DI\Definition\Helper\DefinitionHelper;
-use DI\DependencyException;
-use Exception;
-
-/**
- * Resolves an array definition to a value.
- *
- * @since 5.0
- * @author Matthieu Napoli <matthieu@mnapoli.fr>
- */
-class ArrayResolver implements DefinitionResolver
-{
- /**
- * @var DefinitionResolver
- */
- private $definitionResolver;
-
- /**
- * @param DefinitionResolver $definitionResolver Used to resolve nested definitions.
- */
- public function __construct(DefinitionResolver $definitionResolver)
- {
- $this->definitionResolver = $definitionResolver;
- }
-
- /**
- * Resolve an array definition to a value.
- *
- * An array definition can contain simple values or references to other entries.
- *
- * @param ArrayDefinition $definition
- *
- * {@inheritdoc}
- */
- public function resolve(Definition $definition, array $parameters = [])
- {
- $values = $definition->getValues();
-
- $values = $this->resolveNestedDefinitions($definition, $values);
-
- return $values;
- }
-
- /**
- * {@inheritdoc}
- */
- public function isResolvable(Definition $definition, array $parameters = [])
- {
- return true;
- }
-
- private function resolveNestedDefinitions(ArrayDefinition $definition, array $values)
- {
- foreach ($values as $key => $value) {
- if ($value instanceof DefinitionHelper) {
- $values[$key] = $this->resolveDefinition($value, $definition, $key);
- }
- }
-
- return $values;
- }
-
- private function resolveDefinition(DefinitionHelper $value, ArrayDefinition $definition, $key)
- {
- try {
- return $this->definitionResolver->resolve($value->getDefinition(''));
- } catch (DependencyException $e) {
- throw $e;
- } catch (Exception $e) {
- throw new DependencyException(sprintf(
- "Error while resolving %s[%s]. %s",
- $definition->getName(),
- $key,
- $e->getMessage()
- ), 0, $e);
- }
- }
-}
+++ /dev/null
-<?php
-/**
- * PHP-DI
- *
- * @link http://mnapoli.github.com/PHP-DI/
- * @copyright Matthieu Napoli (http://mnapoli.fr/)
- * @license http://www.opensource.org/licenses/mit-license.php MIT (see the LICENSE file)
- */
-
-namespace DI\Definition\Resolver;
-
-use DI\Definition\DecoratorDefinition;
-use DI\Definition\Exception\DefinitionException;
-use DI\Definition\Definition;
-use Interop\Container\ContainerInterface;
-
-/**
- * Resolves a decorator definition to a value.
- *
- * @since 5.0
- * @author Matthieu Napoli <matthieu@mnapoli.fr>
- */
-class DecoratorResolver implements DefinitionResolver
-{
- /**
- * @var ContainerInterface
- */
- private $container;
-
- /**
- * @var DefinitionResolver
- */
- private $definitionResolver;
-
- /**
- * The resolver needs a container. This container will be passed to the factory as a parameter
- * so that the factory can access other entries of the container.
- *
- * @param ContainerInterface $container
- * @param DefinitionResolver $definitionResolver Used to resolve nested definitions.
- */
- public function __construct(ContainerInterface $container, DefinitionResolver $definitionResolver)
- {
- $this->container = $container;
- $this->definitionResolver = $definitionResolver;
- }
-
- /**
- * Resolve a decorator definition to a value.
- *
- * This will call the callable of the definition and pass it the decorated entry.
- *
- * @param DecoratorDefinition $definition
- *
- * {@inheritdoc}
- */
- public function resolve(Definition $definition, array $parameters = [])
- {
- $callable = $definition->getCallable();
-
- if (! is_callable($callable)) {
- throw new DefinitionException(sprintf(
- 'The decorator "%s" is not callable',
- $definition->getName()
- ));
- }
-
- $decoratedDefinition = $definition->getDecoratedDefinition();
-
- if (! $decoratedDefinition instanceof Definition) {
- if (! $definition->getSubDefinitionName()) {
- throw new DefinitionException('Decorators cannot be nested in another definition');
- }
-
- throw new DefinitionException(sprintf(
- 'Entry "%s" decorates nothing: no previous definition with the same name was found',
- $definition->getName()
- ));
- }
-
- $decorated = $this->definitionResolver->resolve($decoratedDefinition);
-
- return call_user_func($callable, $decorated, $this->container);
- }
-
- /**
- * {@inheritdoc}
- */
- public function isResolvable(Definition $definition, array $parameters = [])
- {
- return true;
- }
-}
+++ /dev/null
-<?php
-/**
- * PHP-DI
- *
- * @link http://mnapoli.github.com/PHP-DI/
- * @copyright Matthieu Napoli (http://mnapoli.fr/)
- * @license http://www.opensource.org/licenses/mit-license.php MIT (see the LICENSE file)
- */
-
-namespace DI\Definition\Resolver;
-
-use DI\Definition\Definition;
-use DI\Definition\Exception\DefinitionException;
-
-/**
- * Resolves a definition to a value.
- *
- * @since 4.0
- * @author Matthieu Napoli <matthieu@mnapoli.fr>
- */
-interface DefinitionResolver
-{
- /**
- * Resolve a definition to a value.
- *
- * @param Definition $definition Object that defines how the value should be obtained.
- * @param array $parameters Optional parameters to use to build the entry.
- *
- * @throws DefinitionException If the definition cannot be resolved.
- *
- * @return mixed Value obtained from the definition.
- */
- public function resolve(Definition $definition, array $parameters = []);
-
- /**
- * Check if a definition can be resolved.
- *
- * @param Definition $definition Object that defines how the value should be obtained.
- * @param array $parameters Optional parameters to use to build the entry.
- *
- * @return bool
- */
- public function isResolvable(Definition $definition, array $parameters = []);
-}
+++ /dev/null
-<?php
-/**
- * PHP-DI
- *
- * @link http://mnapoli.github.com/PHP-DI/
- * @copyright Matthieu Napoli (http://mnapoli.fr/)
- * @license http://www.opensource.org/licenses/mit-license.php MIT (see the LICENSE file)
- */
-
-namespace DI\Definition\Resolver;
-
-use DI\Definition\Definition;
-use DI\Definition\EnvironmentVariableDefinition;
-use DI\Definition\Exception\DefinitionException;
-use DI\Definition\Helper\DefinitionHelper;
-
-/**
- * Resolves a environment variable definition to a value.
- *
- * @author James Harris <james.harris@icecave.com.au>
- */
-class EnvironmentVariableResolver implements DefinitionResolver
-{
- /**
- * @var DefinitionResolver
- */
- private $definitionResolver;
-
- /**
- * @var callable
- */
- private $variableReader;
-
- public function __construct(DefinitionResolver $definitionResolver, $variableReader = 'getenv')
- {
- $this->definitionResolver = $definitionResolver;
- $this->variableReader = $variableReader;
- }
-
- /**
- * Resolve an environment variable definition to a value.
- *
- * @param EnvironmentVariableDefinition $definition
- *
- * {@inheritdoc}
- */
- public function resolve(Definition $definition, array $parameters = [])
- {
- $value = call_user_func($this->variableReader, $definition->getVariableName());
-
- if (false !== $value) {
- return $value;
- }
-
- if (!$definition->isOptional()) {
- throw new DefinitionException(sprintf(
- "The environment variable '%s' has not been defined",
- $definition->getVariableName()
- ));
- }
-
- $value = $definition->getDefaultValue();
-
- // Nested definition
- if ($value instanceof DefinitionHelper) {
- return $this->definitionResolver->resolve($value->getDefinition(''));
- }
-
- return $value;
- }
-
- /**
- * @param EnvironmentVariableDefinition $definition
- *
- * {@inheritdoc}
- */
- public function isResolvable(Definition $definition, array $parameters = [])
- {
- return true;
- }
-}
+++ /dev/null
-<?php
-/**
- * PHP-DI
- *
- * @link http://mnapoli.github.com/PHP-DI/
- * @copyright Matthieu Napoli (http://mnapoli.fr/)
- * @license http://www.opensource.org/licenses/mit-license.php MIT (see the LICENSE file)
- */
-
-namespace DI\Definition\Resolver;
-
-use DI\Definition\Exception\DefinitionException;
-use DI\Definition\FactoryDefinition;
-use DI\Definition\Definition;
-use Interop\Container\ContainerInterface;
-use Invoker\Invoker;
-use Invoker\ParameterResolver\NumericArrayResolver;
-
-/**
- * Resolves a factory definition to a value.
- *
- * @since 4.0
- * @author Matthieu Napoli <matthieu@mnapoli.fr>
- */
-class FactoryResolver implements DefinitionResolver
-{
- /**
- * @var ContainerInterface
- */
- private $container;
-
- /**
- * @var Invoker|null
- */
- private $invoker;
-
- /**
- * The resolver needs a container. This container will be passed to the factory as a parameter
- * so that the factory can access other entries of the container.
- *
- * @param ContainerInterface $container
- */
- public function __construct(ContainerInterface $container)
- {
- $this->container = $container;
- }
-
- /**
- * Resolve a factory definition to a value.
- *
- * This will call the callable of the definition.
- *
- * @param FactoryDefinition $definition
- *
- * {@inheritdoc}
- */
- public function resolve(Definition $definition, array $parameters = [])
- {
- $callable = $definition->getCallable();
-
- if (! is_callable($callable)) {
- throw new DefinitionException(sprintf(
- 'The factory definition "%s" is not callable',
- $definition->getName()
- ));
- }
-
- if (! $this->invoker) {
- $this->invoker = new Invoker(new NumericArrayResolver, $this->container);
- }
-
- return $this->invoker->call($callable, [$this->container]);
- }
-
- /**
- * {@inheritdoc}
- */
- public function isResolvable(Definition $definition, array $parameters = [])
- {
- return true;
- }
-}
+++ /dev/null
-<?php
-/**
- * PHP-DI
- *
- * @link http://mnapoli.github.com/PHP-DI/
- * @copyright Matthieu Napoli (http://mnapoli.fr/)
- * @license http://www.opensource.org/licenses/mit-license.php MIT (see the LICENSE file)
- */
-
-namespace DI\Definition\Resolver;
-
-use DI\Definition\Definition;
-use DI\Definition\InstanceDefinition;
-use DI\DependencyException;
-use Interop\Container\Exception\NotFoundException;
-
-/**
- * Injects dependencies on an existing instance.
- *
- * @since 5.0
- * @author Matthieu Napoli <matthieu@mnapoli.fr>
- */
-class InstanceInjector extends ObjectCreator
-{
- /**
- * Injects dependencies on an existing instance.
- *
- * @param InstanceDefinition $definition
- *
- * {@inheritdoc}
- */
- public function resolve(Definition $definition, array $parameters = [])
- {
- try {
- $this->injectMethodsAndProperties($definition->getInstance(), $definition->getObjectDefinition());
- } catch (NotFoundException $e) {
- $message = sprintf(
- "Error while injecting dependencies into %s: %s",
- get_class($definition->getInstance()),
- $e->getMessage()
- );
- throw new DependencyException($message, 0, $e);
- }
- }
-
- /**
- * {@inheritdoc}
- */
- public function isResolvable(Definition $definition, array $parameters = [])
- {
- return true;
- }
-}
+++ /dev/null
-<?php
-/**
- * PHP-DI
- *
- * @link http://mnapoli.github.com/PHP-DI/
- * @copyright Matthieu Napoli (http://mnapoli.fr/)
- * @license http://www.opensource.org/licenses/mit-license.php MIT (see the LICENSE file)
- */
-
-namespace DI\Definition\Resolver;
-
-use DI\Definition\ObjectDefinition;
-use DI\Definition\Definition;
-use DI\Definition\Exception\DefinitionException;
-use DI\Definition\ObjectDefinition\PropertyInjection;
-use DI\Definition\Helper\DefinitionHelper;
-use DI\DependencyException;
-use DI\Proxy\ProxyFactory;
-use Exception;
-use Interop\Container\Exception\NotFoundException;
-use ProxyManager\Proxy\LazyLoadingInterface;
-use ReflectionClass;
-use ReflectionProperty;
-
-/**
- * Create objects based on an object definition.
- *
- * @since 4.0
- * @author Matthieu Napoli <matthieu@mnapoli.fr>
- */
-class ObjectCreator implements DefinitionResolver
-{
- /**
- * @var ProxyFactory
- */
- private $proxyFactory;
-
- /**
- * @var ParameterResolver
- */
- private $parameterResolver;
-
- /**
- * @var DefinitionResolver
- */
- private $definitionResolver;
-
- /**
- * @param DefinitionResolver $definitionResolver Used to resolve nested definitions.
- * @param ProxyFactory $proxyFactory Used to create proxies for lazy injections.
- */
- public function __construct(
- DefinitionResolver $definitionResolver,
- ProxyFactory $proxyFactory
- ) {
- $this->definitionResolver = $definitionResolver;
- $this->proxyFactory = $proxyFactory;
- $this->parameterResolver = new ParameterResolver($definitionResolver);
- }
-
- /**
- * Resolve a class definition to a value.
- *
- * This will create a new instance of the class using the injections points defined.
- *
- * @param ObjectDefinition $definition
- *
- * {@inheritdoc}
- */
- public function resolve(Definition $definition, array $parameters = [])
- {
- // Lazy?
- if ($definition->isLazy()) {
- return $this->createProxy($definition, $parameters);
- }
-
- return $this->createInstance($definition, $parameters);
- }
-
- /**
- * The definition is not resolvable if the class is not instantiable (interface or abstract)
- * or if the class doesn't exist.
- *
- * @param ObjectDefinition $definition
- *
- * {@inheritdoc}
- */
- public function isResolvable(Definition $definition, array $parameters = [])
- {
- return $definition->isInstantiable();
- }
-
- /**
- * Returns a proxy instance
- *
- * @param ObjectDefinition $definition
- * @param array $parameters
- *
- * @return LazyLoadingInterface Proxy instance
- */
- private function createProxy(ObjectDefinition $definition, array $parameters)
- {
- /** @noinspection PhpUnusedParameterInspection */
- $proxy = $this->proxyFactory->createProxy(
- $definition->getClassName(),
- function (& $wrappedObject, $proxy, $method, $params, & $initializer) use ($definition, $parameters) {
- $wrappedObject = $this->createInstance($definition, $parameters);
- $initializer = null; // turning off further lazy initialization
- return true;
- }
- );
-
- return $proxy;
- }
-
- /**
- * Creates an instance of the class and injects dependencies..
- *
- * @param ObjectDefinition $definition
- * @param array $parameters Optional parameters to use to create the instance.
- *
- * @throws DefinitionException
- * @throws DependencyException
- * @return object
- */
- private function createInstance(ObjectDefinition $definition, array $parameters)
- {
- $this->assertClassExists($definition);
-
- $classname = $definition->getClassName();
- $classReflection = new ReflectionClass($classname);
-
- $this->assertClassIsInstantiable($definition);
-
- $constructorInjection = $definition->getConstructorInjection();
-
- try {
- $args = $this->parameterResolver->resolveParameters(
- $constructorInjection,
- $classReflection->getConstructor(),
- $parameters
- );
-
- if (count($args) > 0) {
- $object = $classReflection->newInstanceArgs($args);
- } else {
- $object = new $classname;
- }
-
- $this->injectMethodsAndProperties($object, $definition);
- } catch (NotFoundException $e) {
- throw new DependencyException(sprintf(
- "Error while injecting dependencies into %s: %s",
- $classReflection->getName(),
- $e->getMessage()
- ), 0, $e);
- } catch (DefinitionException $e) {
- throw DefinitionException::create($definition, sprintf(
- "Entry %s cannot be resolved: %s",
- $definition->getName(),
- $e->getMessage()
- ));
- }
-
- if (! $object) {
- throw new DependencyException(sprintf(
- "Entry %s cannot be resolved: %s could not be constructed",
- $definition->getName(),
- $classReflection->getName()
- ));
- }
-
- return $object;
- }
-
- protected function injectMethodsAndProperties($object, ObjectDefinition $objectDefinition)
- {
- // Property injections
- foreach ($objectDefinition->getPropertyInjections() as $propertyInjection) {
- $this->injectProperty($object, $propertyInjection);
- }
-
- // Method injections
- foreach ($objectDefinition->getMethodInjections() as $methodInjection) {
- $methodReflection = new \ReflectionMethod($object, $methodInjection->getMethodName());
- $args = $this->parameterResolver->resolveParameters($methodInjection, $methodReflection);
-
- $methodReflection->invokeArgs($object, $args);
- }
- }
-
- /**
- * Inject dependencies into properties.
- *
- * @param object $object Object to inject dependencies into
- * @param PropertyInjection $propertyInjection Property injection definition
- *
- * @throws DependencyException
- * @throws DefinitionException
- */
- private function injectProperty($object, PropertyInjection $propertyInjection)
- {
- $propertyName = $propertyInjection->getPropertyName();
-
- $className = $propertyInjection->getClassName();
- $className = $className ?: get_class($object);
- $property = new ReflectionProperty($className, $propertyName);
-
- $value = $propertyInjection->getValue();
-
- if ($value instanceof DefinitionHelper) {
- /** @var Definition $nestedDefinition */
- $nestedDefinition = $value->getDefinition('');
-
- try {
- $value = $this->definitionResolver->resolve($nestedDefinition);
- } catch (DependencyException $e) {
- throw $e;
- } catch (Exception $e) {
- throw new DependencyException(sprintf(
- "Error while injecting in %s::%s. %s",
- get_class($object),
- $propertyName,
- $e->getMessage()
- ), 0, $e);
- }
- }
-
- if (! $property->isPublic()) {
- $property->setAccessible(true);
- }
- $property->setValue($object, $value);
- }
-
- private function assertClassExists(ObjectDefinition $definition)
- {
- if (! $definition->classExists()) {
- throw DefinitionException::create($definition,
- sprintf(
- "Entry %s cannot be resolved: class %s doesn't exist",
- $definition->getName(),
- $definition->getClassName()
- ));
- }
- }
-
- private function assertClassIsInstantiable(ObjectDefinition $definition)
- {
- if (! $definition->isInstantiable()) {
- throw DefinitionException::create($definition,
- sprintf(
- "Entry %s cannot be resolved: class %s is not instantiable",
- $definition->getName(),
- $definition->getClassName()
- ));
- }
- }
-}
+++ /dev/null
-<?php
-/**
- * PHP-DI
- *
- * @link http://mnapoli.github.com/PHP-DI/
- * @copyright Matthieu Napoli (http://mnapoli.fr/)
- * @license http://www.opensource.org/licenses/mit-license.php MIT (see the LICENSE file)
- */
-
-namespace DI\Definition\Resolver;
-
-use DI\Definition\ObjectDefinition;
-use DI\Definition\Exception\DefinitionException;
-use DI\Definition\Helper\DefinitionHelper;
-use DI\Definition\ObjectDefinition\MethodInjection;
-
-/**
- * Resolves parameters for a function call.
- *
- * @since 4.2
- * @author Matthieu Napoli <matthieu@mnapoli.fr>
- */
-class ParameterResolver
-{
- /**
- * @var DefinitionResolver
- */
- private $definitionResolver;
-
- /**
- * @param DefinitionResolver $definitionResolver Will be used to resolve nested definitions.
- */
- public function __construct(DefinitionResolver $definitionResolver)
- {
- $this->definitionResolver = $definitionResolver;
- }
-
- /**
- * @param MethodInjection $definition
- * @param \ReflectionFunctionAbstract $functionReflection
- * @param array $parameters
- *
- * @throws DefinitionException A parameter has no value defined or guessable.
- * @return array Parameters to use to call the function.
- */
- public function resolveParameters(
- MethodInjection $definition = null,
- \ReflectionFunctionAbstract $functionReflection = null,
- array $parameters = []
- ) {
- $args = [];
-
- if (! $functionReflection) {
- return $args;
- }
-
- $definitionParameters = $definition ? $definition->getParameters() : array();
-
- foreach ($functionReflection->getParameters() as $index => $parameter) {
- if (array_key_exists($parameter->getName(), $parameters)) {
- // Look in the $parameters array
- $value = &$parameters[$parameter->getName()];
- } elseif (array_key_exists($index, $definitionParameters)) {
- // Look in the definition
- $value = &$definitionParameters[$index];
- } else {
- // If the parameter is optional and wasn't specified, we take its default value
- if ($parameter->isOptional()) {
- $args[] = $this->getParameterDefaultValue($parameter, $functionReflection);
- continue;
- }
-
- throw new DefinitionException(sprintf(
- "The parameter '%s' of %s has no value defined or guessable",
- $parameter->getName(),
- $this->getFunctionName($functionReflection)
- ));
- }
-
- if ($value instanceof DefinitionHelper) {
- $nestedDefinition = $value->getDefinition('');
-
- // If the container cannot produce the entry, we can use the default parameter value
- if ($parameter->isOptional() && !$this->definitionResolver->isResolvable($nestedDefinition)) {
- $value = $this->getParameterDefaultValue($parameter, $functionReflection);
- } else {
- $value = $this->definitionResolver->resolve($nestedDefinition);
- }
- }
-
- $args[] = &$value;
- }
-
- return $args;
- }
-
- /**
- * Returns the default value of a function parameter.
- *
- * @param \ReflectionParameter $parameter
- * @param \ReflectionFunctionAbstract $function
- *
- * @throws DefinitionException Can't get default values from PHP internal classes and functions
- * @return mixed
- */
- private function getParameterDefaultValue(
- \ReflectionParameter $parameter,
- \ReflectionFunctionAbstract $function
- ) {
- try {
- return $parameter->getDefaultValue();
- } catch (\ReflectionException $e) {
- throw new DefinitionException(sprintf(
- "The parameter '%s' of %s has no type defined or guessable. It has a default value, "
- . "but the default value can't be read through Reflection because it is a PHP internal class.",
- $parameter->getName(),
- $this->getFunctionName($function)
- ));
- }
- }
-
- private function getFunctionName(\ReflectionFunctionAbstract $reflectionFunction)
- {
- if ($reflectionFunction instanceof \ReflectionMethod) {
- return sprintf(
- '%s::%s',
- $reflectionFunction->getDeclaringClass()->getName(),
- $reflectionFunction->getName()
- );
- } elseif ($reflectionFunction->isClosure()) {
- return sprintf(
- 'closure defined in %s at line %d',
- $reflectionFunction->getFileName(),
- $reflectionFunction->getStartLine()
- );
- }
-
- return $reflectionFunction->getName();
- }
-}
+++ /dev/null
-<?php
-
-namespace DI\Definition\Resolver;
-
-use DI\Definition\Definition;
-use DI\Definition\Exception\DefinitionException;
-use DI\Proxy\ProxyFactory;
-use Interop\Container\ContainerInterface;
-
-/**
- * Dispatches to more specific resolvers.
- *
- * Dynamic dispatch pattern.
- *
- * @since 5.0
- * @author Matthieu Napoli <matthieu@mnapoli.fr>
- */
-class ResolverDispatcher implements DefinitionResolver
-{
- /**
- * @var ContainerInterface
- */
- private $container;
-
- /**
- * @var ProxyFactory
- */
- private $proxyFactory;
-
- private $valueResolver;
- private $arrayResolver;
- private $factoryResolver;
- private $decoratorResolver;
- private $aliasResolver;
- private $objectResolver;
- private $instanceResolver;
- private $envVariableResolver;
- private $stringResolver;
-
- public function __construct(ContainerInterface $container, ProxyFactory $proxyFactory)
- {
- $this->container = $container;
- $this->proxyFactory = $proxyFactory;
- }
-
- /**
- * Resolve a definition to a value.
- *
- * @param Definition $definition Object that defines how the value should be obtained.
- * @param array $parameters Optional parameters to use to build the entry.
- *
- * @throws DefinitionException If the definition cannot be resolved.
- *
- * @return mixed Value obtained from the definition.
- */
- public function resolve(Definition $definition, array $parameters = [])
- {
- $definitionResolver = $this->getDefinitionResolver($definition);
-
- return $definitionResolver->resolve($definition, $parameters);
- }
-
- /**
- * Check if a definition can be resolved.
- *
- * @param Definition $definition Object that defines how the value should be obtained.
- * @param array $parameters Optional parameters to use to build the entry.
- *
- * @return bool
- */
- public function isResolvable(Definition $definition, array $parameters = [])
- {
- $definitionResolver = $this->getDefinitionResolver($definition);
-
- return $definitionResolver->isResolvable($definition, $parameters);
- }
-
- /**
- * Returns a resolver capable of handling the given definition.
- *
- * @param Definition $definition
- *
- * @throws \RuntimeException No definition resolver was found for this type of definition.
- * @return DefinitionResolver
- */
- private function getDefinitionResolver(Definition $definition)
- {
- switch (true) {
- case ($definition instanceof \DI\Definition\ObjectDefinition):
- if (! $this->objectResolver) {
- $this->objectResolver = new ObjectCreator($this, $this->proxyFactory);
- }
- return $this->objectResolver;
- case ($definition instanceof \DI\Definition\ValueDefinition):
- if (! $this->valueResolver) {
- $this->valueResolver = new ValueResolver();
- }
- return $this->valueResolver;
- case ($definition instanceof \DI\Definition\AliasDefinition):
- if (! $this->aliasResolver) {
- $this->aliasResolver = new AliasResolver($this->container);
- }
- return $this->aliasResolver;
- case ($definition instanceof \DI\Definition\DecoratorDefinition):
- if (! $this->decoratorResolver) {
- $this->decoratorResolver = new DecoratorResolver($this->container, $this);
- }
- return $this->decoratorResolver;
- case ($definition instanceof \DI\Definition\FactoryDefinition):
- if (! $this->factoryResolver) {
- $this->factoryResolver = new FactoryResolver($this->container);
- }
- return $this->factoryResolver;
- case ($definition instanceof \DI\Definition\ArrayDefinition):
- if (! $this->arrayResolver) {
- $this->arrayResolver = new ArrayResolver($this);
- }
- return $this->arrayResolver;
- case ($definition instanceof \DI\Definition\EnvironmentVariableDefinition):
- if (! $this->envVariableResolver) {
- $this->envVariableResolver = new EnvironmentVariableResolver($this);
- }
- return $this->envVariableResolver;
- case ($definition instanceof \DI\Definition\StringDefinition):
- if (! $this->stringResolver) {
- $this->stringResolver = new StringResolver($this->container);
- }
- return $this->stringResolver;
- case ($definition instanceof \DI\Definition\InstanceDefinition):
- if (! $this->instanceResolver) {
- $this->instanceResolver = new InstanceInjector($this, $this->proxyFactory);
- }
- return $this->instanceResolver;
- default:
- throw new \RuntimeException('No definition resolver was configured for definition of type ' . get_class($definition));
- }
- }
-}
+++ /dev/null
-<?php
-/**
- * PHP-DI
- *
- * @link http://mnapoli.github.com/PHP-DI/
- * @copyright Matthieu Napoli (http://mnapoli.fr/)
- * @license http://www.opensource.org/licenses/mit-license.php MIT (see the LICENSE file)
- */
-
-namespace DI\Definition\Resolver;
-
-use DI\Definition\Definition;
-use DI\Definition\StringDefinition;
-use DI\DependencyException;
-use DI\NotFoundException;
-use Interop\Container\ContainerInterface;
-
-/**
- * Resolves a string expression.
- *
- * @since 5.0
- * @author Matthieu Napoli <matthieu@mnapoli.fr>
- */
-class StringResolver implements DefinitionResolver
-{
- /**
- * @var ContainerInterface
- */
- private $container;
-
- /**
- * The resolver needs a container.
- * This container will be used to get the entry to which the alias points to.
- *
- * @param ContainerInterface $container
- */
- public function __construct(ContainerInterface $container)
- {
- $this->container = $container;
- }
-
- /**
- * Resolve a value definition to a value.
- *
- * A value definition is simple, so this will just return the value of the ValueDefinition.
- *
- * @param StringDefinition $definition
- *
- * {@inheritdoc}
- */
- public function resolve(Definition $definition, array $parameters = [])
- {
- $expression = $definition->getExpression();
-
- $result = preg_replace_callback('#\{([^\{\}]+)\}#', function (array $matches) use ($definition) {
- try {
- return $this->container->get($matches[1]);
- } catch (NotFoundException $e) {
- throw new DependencyException(sprintf(
- "Error while parsing string expression for entry '%s': %s",
- $definition->getName(),
- $e->getMessage()
- ), 0, $e);
- }
- }, $expression);
-
- if ($result === null) {
- throw new \RuntimeException(sprintf('An unknown error occurred while parsing the string definition: \'%s\'', $expression));
- }
-
- return $result;
- }
-
- /**
- * {@inheritdoc}
- */
- public function isResolvable(Definition $definition, array $parameters = [])
- {
- return true;
- }
-}
+++ /dev/null
-<?php
-/**
- * PHP-DI
- *
- * @link http://mnapoli.github.com/PHP-DI/
- * @copyright Matthieu Napoli (http://mnapoli.fr/)
- * @license http://www.opensource.org/licenses/mit-license.php MIT (see the LICENSE file)
- */
-
-namespace DI\Definition\Resolver;
-
-use DI\Definition\Definition;
-use DI\Definition\ValueDefinition;
-
-/**
- * Resolves a value definition to a value.
- *
- * @since 4.0
- * @author Matthieu Napoli <matthieu@mnapoli.fr>
- */
-class ValueResolver implements DefinitionResolver
-{
- /**
- * Resolve a value definition to a value.
- *
- * A value definition is simple, so this will just return the value of the ValueDefinition.
- *
- * @param ValueDefinition $definition
- *
- * {@inheritdoc}
- */
- public function resolve(Definition $definition, array $parameters = [])
- {
- return $definition->getValue();
- }
-
- /**
- * {@inheritdoc}
- */
- public function isResolvable(Definition $definition, array $parameters = [])
- {
- return true;
- }
-}
+++ /dev/null
-<?php
-/**
- * PHP-DI
- *
- * @link http://php-di.org/
- * @copyright Matthieu Napoli (http://mnapoli.fr/)
- * @license http://www.opensource.org/licenses/mit-license.php MIT (see the LICENSE file)
- */
-
-namespace DI\Definition\Source;
-
-use DI\Annotation\Inject;
-use DI\Annotation\Injectable;
-use DI\Definition\ObjectDefinition;
-use DI\Definition\EntryReference;
-use DI\Definition\Exception\AnnotationException;
-use DI\Definition\Exception\DefinitionException;
-use DI\Definition\ObjectDefinition\MethodInjection;
-use DI\Definition\ObjectDefinition\PropertyInjection;
-use Doctrine\Common\Annotations\AnnotationRegistry;
-use Doctrine\Common\Annotations\Reader;
-use Doctrine\Common\Annotations\SimpleAnnotationReader;
-use InvalidArgumentException;
-use PhpDocReader\PhpDocReader;
-use ReflectionClass;
-use ReflectionMethod;
-use ReflectionParameter;
-use ReflectionProperty;
-use UnexpectedValueException;
-
-/**
- * Provides DI definitions by reading annotations such as @ Inject and @ var annotations.
- *
- * Uses Autowiring, Doctrine's Annotations and regex docblock parsing.
- * This source automatically includes the reflection source.
- *
- * @author Matthieu Napoli <matthieu@mnapoli.fr>
- */
-class AnnotationReader implements DefinitionSource
-{
- /**
- * @var Reader
- */
- private $annotationReader;
-
- /**
- * @var PhpDocReader
- */
- private $phpDocReader;
-
- /**
- * @var bool
- */
- private $ignorePhpDocErrors;
-
- public function __construct($ignorePhpDocErrors = false)
- {
- $this->ignorePhpDocErrors = (bool) $ignorePhpDocErrors;
- }
-
- /**
- * {@inheritdoc}
- * @throws AnnotationException
- * @throws InvalidArgumentException The class doesn't exist
- */
- public function getDefinition($name)
- {
- if (!class_exists($name) && !interface_exists($name)) {
- return null;
- }
-
- $class = new ReflectionClass($name);
- $definition = new ObjectDefinition($name);
-
- $this->readInjectableAnnotation($class, $definition);
-
- // Browse the class properties looking for annotated properties
- $this->readProperties($class, $definition);
-
- // Browse the object's methods looking for annotated methods
- $this->readMethods($class, $definition);
-
- return $definition;
- }
-
- /**
- * Browse the class properties looking for annotated properties.
- */
- private function readProperties(ReflectionClass $class, ObjectDefinition $definition)
- {
- foreach ($class->getProperties() as $property) {
- if ($property->isStatic()) {
- continue;
- }
- $this->readProperty($property, $definition);
- }
-
- // Read also the *private* properties of the parent classes
- /** @noinspection PhpAssignmentInConditionInspection */
- while ($class = $class->getParentClass()) {
- foreach ($class->getProperties(ReflectionProperty::IS_PRIVATE) as $property) {
- if ($property->isStatic()) {
- continue;
- }
- $this->readProperty($property, $definition, $class->getName());
- }
- }
- }
-
- private function readProperty(ReflectionProperty $property, ObjectDefinition $definition, $classname = null)
- {
- // Look for @Inject annotation
- /** @var $annotation Inject */
- $annotation = $this->getAnnotationReader()->getPropertyAnnotation($property, 'DI\Annotation\Inject');
- if ($annotation === null) {
- return null;
- }
-
- // @Inject("name") or look for @var content
- $entryName = $annotation->getName() ?: $this->getPhpDocReader()->getPropertyClass($property);
-
- if ($entryName === null) {
- throw new AnnotationException(sprintf(
- '@Inject found on property %s::%s but unable to guess what to inject, use a @var annotation',
- $property->getDeclaringClass()->getName(),
- $property->getName()
- ));
- }
-
- $definition->addPropertyInjection(
- new PropertyInjection($property->getName(), new EntryReference($entryName), $classname)
- );
- }
-
- /**
- * Browse the object's methods looking for annotated methods.
- */
- private function readMethods(ReflectionClass $class, ObjectDefinition $objectDefinition)
- {
- // This will look in all the methods, including those of the parent classes
- foreach ($class->getMethods(ReflectionMethod::IS_PUBLIC) as $method) {
- if ($method->isStatic()) {
- continue;
- }
-
- $methodInjection = $this->getMethodInjection($method);
-
- if (! $methodInjection) {
- continue;
- }
-
- if ($method->isConstructor()) {
- $objectDefinition->setConstructorInjection($methodInjection);
- } else {
- $objectDefinition->addMethodInjection($methodInjection);
- }
- }
- }
-
- private function getMethodInjection(ReflectionMethod $method)
- {
- // Look for @Inject annotation
- /** @var $annotation Inject|null */
- try {
- $annotation = $this->getAnnotationReader()->getMethodAnnotation($method, 'DI\Annotation\Inject');
- } catch (AnnotationException $e) {
- throw new AnnotationException(sprintf(
- '@Inject annotation on %s::%s is malformed. %s',
- $method->getDeclaringClass()->getName(),
- $method->getName(),
- $e->getMessage()
- ), 0, $e);
- }
- $annotationParameters = $annotation ? $annotation->getParameters() : [];
-
- // @Inject on constructor is implicit
- if (! ($annotation || $method->isConstructor())) {
- return null;
- }
-
- $parameters = [];
- foreach ($method->getParameters() as $index => $parameter) {
- $entryName = $this->getMethodParameter($index, $parameter, $annotationParameters);
-
- if ($entryName !== null) {
- $parameters[$index] = new EntryReference($entryName);
- }
- }
-
- if ($method->isConstructor()) {
- return MethodInjection::constructor($parameters);
- } else {
- return new MethodInjection($method->getName(), $parameters);
- }
- }
-
- /**
- * @param int $parameterIndex
- * @param ReflectionParameter $parameter
- * @param array $annotationParameters
- *
- * @return string|null Entry name or null if not found.
- */
- private function getMethodParameter($parameterIndex, ReflectionParameter $parameter, array $annotationParameters)
- {
- // @Inject has definition for this parameter (by index, or by name)
- if (isset($annotationParameters[$parameterIndex])) {
- return $annotationParameters[$parameterIndex];
- }
- if (isset($annotationParameters[$parameter->getName()])) {
- return $annotationParameters[$parameter->getName()];
- }
-
- // Skip optional parameters if not explicitly defined
- if ($parameter->isOptional()) {
- return null;
- }
-
- // Try to use the type-hinting
- $parameterClass = $parameter->getClass();
- if ($parameterClass) {
- return $parameterClass->getName();
- }
-
- // Last resort, look for @param tag
- return $this->getPhpDocReader()->getParameterClass($parameter);
- }
-
- /**
- * @return Reader The annotation reader
- */
- public function getAnnotationReader()
- {
- if ($this->annotationReader === null) {
- AnnotationRegistry::registerAutoloadNamespace('DI\Annotation', __DIR__ . '/../../../');
- $this->annotationReader = new SimpleAnnotationReader();
- $this->annotationReader->addNamespace('DI\Annotation');
- }
-
- return $this->annotationReader;
- }
-
- /**
- * @return PhpDocReader
- */
- private function getPhpDocReader()
- {
- if ($this->phpDocReader === null) {
- $this->phpDocReader = new PhpDocReader($this->ignorePhpDocErrors);
- }
-
- return $this->phpDocReader;
- }
-
- private function readInjectableAnnotation(ReflectionClass $class, ObjectDefinition $definition)
- {
- try {
- /** @var $annotation Injectable|null */
- $annotation = $this->getAnnotationReader()
- ->getClassAnnotation($class, 'DI\Annotation\Injectable');
- } catch (UnexpectedValueException $e) {
- throw new DefinitionException(sprintf(
- 'Error while reading @Injectable on %s: %s',
- $class->getName(),
- $e->getMessage()
- ), 0, $e);
- }
-
- if (! $annotation) {
- return;
- }
-
- if ($annotation->getScope()) {
- $definition->setScope($annotation->getScope());
- }
- if ($annotation->isLazy() !== null) {
- $definition->setLazy($annotation->isLazy());
- }
- }
-}
+++ /dev/null
-<?php
-/**
- * PHP-DI
- *
- * @link http://php-di.org/
- * @copyright Matthieu Napoli (http://mnapoli.fr/)
- * @license http://www.opensource.org/licenses/mit-license.php MIT (see the LICENSE file)
- */
-
-namespace DI\Definition\Source;
-
-use DI\Definition\ObjectDefinition;
-use DI\Definition\EntryReference;
-use DI\Definition\ObjectDefinition\MethodInjection;
-
-/**
- * Reads DI class definitions using reflection.
- *
- * @author Matthieu Napoli <matthieu@mnapoli.fr>
- */
-class Autowiring implements DefinitionSource
-{
- /**
- * {@inheritdoc}
- */
- public function getDefinition($name)
- {
- if (!class_exists($name) && !interface_exists($name)) {
- return null;
- }
-
- $definition = new ObjectDefinition($name);
-
- // Constructor
- $class = new \ReflectionClass($name);
- $constructor = $class->getConstructor();
- if ($constructor && $constructor->isPublic()) {
- $definition->setConstructorInjection(
- MethodInjection::constructor($this->getParametersDefinition($constructor))
- );
- }
-
- return $definition;
- }
-
- /**
- * Read the type-hinting from the parameters of the function.
- */
- private function getParametersDefinition(\ReflectionFunctionAbstract $constructor)
- {
- $parameters = [];
-
- foreach ($constructor->getParameters() as $index => $parameter) {
- // Skip optional parameters
- if ($parameter->isOptional()) {
- continue;
- }
-
- $parameterClass = $parameter->getClass();
-
- if ($parameterClass) {
- $parameters[$index] = new EntryReference($parameterClass->getName());
- }
- }
-
- return $parameters;
- }
-}
+++ /dev/null
-<?php
-/**
- * PHP-DI
- *
- * @link http://php-di.org/
- * @copyright Matthieu Napoli (http://mnapoli.fr/)
- * @license http://www.opensource.org/licenses/mit-license.php MIT (see the LICENSE file)
- */
-
-namespace DI\Definition\Source;
-
-use DI\Definition\CacheableDefinition;
-use DI\Definition\Definition;
-use Doctrine\Common\Cache\Cache;
-
-/**
- * Caches another definition source.
- *
- * @author Matthieu Napoli <matthieu@mnapoli.fr>
- */
-class CachedDefinitionSource implements DefinitionSource
-{
- /**
- * Prefix for cache key, to avoid conflicts with other systems using the same cache
- * @var string
- */
- const CACHE_PREFIX = 'DI\\Definition\\';
-
- /**
- * @var DefinitionSource
- */
- private $source;
-
- /**
- * @var Cache
- */
- private $cache;
-
- public function __construct(DefinitionSource $source, Cache $cache)
- {
- $this->source = $source;
- $this->cache = $cache;
- }
-
- /**
- * {@inheritdoc}
- */
- public function getDefinition($name)
- {
- // Look in cache
- $definition = $this->fetchFromCache($name);
-
- if ($definition === false) {
- $definition = $this->source->getDefinition($name);
-
- // Save to cache
- if ($definition === null || ($definition instanceof CacheableDefinition)) {
- $this->saveToCache($name, $definition);
- }
- }
-
- return $definition;
- }
-
- /**
- * @return Cache
- */
- public function getCache()
- {
- return $this->cache;
- }
-
- /**
- * Fetches a definition from the cache
- *
- * @param string $name Entry name
- * @return Definition|null|boolean The cached definition, null or false if the value is not already cached
- */
- private function fetchFromCache($name)
- {
- $cacheKey = self::CACHE_PREFIX . $name;
-
- $data = $this->cache->fetch($cacheKey);
-
- if ($data !== false) {
- return $data;
- }
-
- return false;
- }
-
- /**
- * Saves a definition to the cache
- *
- * @param string $name Entry name
- * @param Definition|null $definition
- */
- private function saveToCache($name, Definition $definition = null)
- {
- $cacheKey = self::CACHE_PREFIX . $name;
-
- $this->cache->save($cacheKey, $definition);
- }
-}
+++ /dev/null
-<?php
-/**
- * PHP-DI
- *
- * @link http://php-di.org/
- * @copyright Matthieu Napoli (http://mnapoli.fr/)
- * @license http://www.opensource.org/licenses/mit-license.php MIT (see the LICENSE file)
- */
-
-namespace DI\Definition\Source;
-
-use DI\Definition\ArrayDefinition;
-use DI\Definition\ObjectDefinition;
-use DI\Definition\Definition;
-use DI\Definition\FactoryDefinition;
-use DI\Definition\ValueDefinition;
-use DI\Definition\Helper\DefinitionHelper;
-
-/**
- * Reads DI definitions from a PHP array.
- *
- * @author Matthieu Napoli <matthieu@mnapoli.fr>
- */
-class DefinitionArray implements DefinitionSource, MutableDefinitionSource
-{
- const WILDCARD = '*';
- /**
- * Matches anything except "\"
- */
- const WILDCARD_PATTERN = '([^\\\\]+)';
-
- /**
- * DI definitions in a PHP array
- * @var array
- */
- private $definitions = [];
-
- /**
- * @param array $definitions
- */
- public function __construct(array $definitions = [])
- {
- $this->definitions = $definitions;
- }
-
- /**
- * @param array $definitions DI definitions in a PHP array indexed by the definition name.
- */
- public function addDefinitions(array $definitions)
- {
- // The newly added data prevails
- // "for keys that exist in both arrays, the elements from the left-hand array will be used"
- $this->definitions = $definitions + $this->definitions;
- }
-
- /**
- * {@inheritdoc}
- */
- public function addDefinition(Definition $definition)
- {
- $this->definitions[$definition->getName()] = $definition;
- }
-
- /**
- * {@inheritdoc}
- */
- public function getDefinition($name)
- {
- // Look for the definition by name
- if (array_key_exists($name, $this->definitions)) {
- return $this->castDefinition($this->definitions[$name], $name);
- }
-
- // Look if there are wildcards definitions
- foreach ($this->definitions as $key => $definition) {
- if (strpos($key, self::WILDCARD) === false) {
- continue;
- }
-
- // Turn the pattern into a regex
- $key = addslashes($key);
- $key = '#' . str_replace(self::WILDCARD, self::WILDCARD_PATTERN, $key) . '#';
- if (preg_match($key, $name, $matches) === 1) {
- $definition = $this->castDefinition($definition, $name);
-
- // For a class definition, we replace * in the class name with the matches
- // *Interface -> *Impl => FooInterface -> FooImpl
- if ($definition instanceof ObjectDefinition) {
- array_shift($matches);
- $definition->setClassName(
- $this->replaceWildcards($definition->getClassName(), $matches)
- );
- }
-
- return $definition;
- }
- }
-
- return null;
- }
-
- /**
- * @param mixed $definition
- * @param string $name
- * @return Definition
- */
- private function castDefinition($definition, $name)
- {
- if ($definition instanceof DefinitionHelper) {
- $definition = $definition->getDefinition($name);
- }
- if (! $definition instanceof Definition && is_array($definition)) {
- $definition = new ArrayDefinition($name, $definition);
- }
- if ($definition instanceof \Closure) {
- $definition = new FactoryDefinition($name, $definition);
- }
- if (! $definition instanceof Definition) {
- $definition = new ValueDefinition($name, $definition);
- }
-
- return $definition;
- }
-
- /**
- * Replaces all the wildcards in the string with the given replacements.
- * @param string $string
- * @param string[] $replacements
- * @return string
- */
- private function replaceWildcards($string, array $replacements)
- {
- foreach ($replacements as $replacement) {
- $pos = strpos($string, self::WILDCARD);
- if ($pos !== false) {
- $string = substr_replace($string, $replacement, $pos, 1);
- }
- }
-
- return $string;
- }
-}
+++ /dev/null
-<?php
-/**
- * PHP-DI
- *
- * @link http://php-di.org/
- * @copyright Matthieu Napoli (http://mnapoli.fr/)
- * @license http://www.opensource.org/licenses/mit-license.php MIT (see the LICENSE file)
- */
-
-namespace DI\Definition\Source;
-
-use DI\Definition\Definition;
-use DI\Definition\Exception\DefinitionException;
-
-/**
- * Reads DI definitions from a file returning a PHP array.
- *
- * @author Matthieu Napoli <matthieu@mnapoli.fr>
- */
-class DefinitionFile extends DefinitionArray
-{
- /**
- * @var bool
- */
- private $initialized = false;
-
- /**
- * File containing definitions, or null if the definitions are given as a PHP array.
- * @var string|null
- */
- private $file;
-
- /**
- * @param string $file File in which the definitions are returned as an array.
- */
- public function __construct($file)
- {
- // Lazy-loading to improve performances
- $this->file = $file;
-
- parent::__construct([]);
- }
-
- /**
- * {@inheritdoc}
- */
- public function getDefinition($name)
- {
- $this->initialize();
-
- return parent::getDefinition($name);
- }
-
- /**
- * Lazy-loading of the definitions.
- * @throws DefinitionException
- */
- private function initialize()
- {
- if ($this->initialized === true) {
- return;
- }
-
- $definitions = require $this->file;
-
- if (! is_array($definitions)) {
- throw new DefinitionException("File {$this->file} should return an array of definitions");
- }
-
- $this->addDefinitions($definitions);
-
- $this->initialized = true;
- }
-}
+++ /dev/null
-<?php
-/**
- * PHP-DI
- *
- * @link http://php-di.org/
- * @copyright Matthieu Napoli (http://mnapoli.fr/)
- * @license http://www.opensource.org/licenses/mit-license.php MIT (see the LICENSE file)
- */
-
-namespace DI\Definition\Source;
-
-use DI\Definition\Definition;
-use DI\Definition\Exception\DefinitionException;
-
-/**
- * Source of definitions for entries of the container.
- *
- * @author Matthieu Napoli <matthieu@mnapoli.fr>
- */
-interface DefinitionSource
-{
- /**
- * Returns the DI definition for the entry name.
- *
- * @param string $name
- *
- * @throws DefinitionException An invalid definition was found.
- * @return Definition|null
- */
- public function getDefinition($name);
-}
+++ /dev/null
-<?php
-
-namespace DI\Definition\Source;
-
-use DI\Definition\Definition;
-
-/**
- * Describes a definition source to which we can add new definitions.
- *
- * @author Matthieu Napoli <matthieu@mnapoli.fr>
- */
-interface MutableDefinitionSource extends DefinitionSource
-{
- public function addDefinition(Definition $definition);
-}
+++ /dev/null
-<?php
-/**
- * PHP-DI
- *
- * @link http://php-di.org/
- * @copyright Matthieu Napoli (http://mnapoli.fr/)
- * @license http://www.opensource.org/licenses/mit-license.php MIT (see the LICENSE file)
- */
-
-namespace DI\Definition\Source;
-
-use DI\Definition\Definition;
-use DI\Definition\HasSubDefinition;
-
-/**
- * Manages a chain of other definition sources.
- *
- * @author Matthieu Napoli <matthieu@mnapoli.fr>
- */
-class SourceChain implements DefinitionSource, MutableDefinitionSource
-{
- /**
- * @var DefinitionSource[]
- */
- private $sources;
-
- /**
- * @var DefinitionSource
- */
- private $rootSource;
-
- /**
- * @var MutableDefinitionSource|null
- */
- private $mutableSource;
-
- /**
- * @param DefinitionSource[] $sources
- */
- public function __construct(array $sources)
- {
- // We want a numerically indexed array to ease the traversal later
- $this->sources = array_values($sources);
- $this->rootSource = $this;
- }
-
- /**
- * {@inheritdoc}
- * @param int $startIndex Use this parameter to start looking from a specific
- * point in the source chain.
- */
- public function getDefinition($name, $startIndex = 0)
- {
- $count = count($this->sources);
- for ($i = $startIndex; $i < $count; $i++) {
- $source = $this->sources[$i];
-
- $definition = $source->getDefinition($name);
-
- if ($definition) {
- if ($definition instanceof HasSubDefinition) {
- $this->resolveSubDefinition($definition, $i);
- }
- return $definition;
- }
- }
-
- return null;
- }
-
- public function addDefinition(Definition $definition)
- {
- if (! $this->mutableSource) {
- throw new \LogicException("The container's definition source has not been initialized correctly");
- }
-
- $this->mutableSource->addDefinition($definition);
- }
-
- public function setRootDefinitionSource(DefinitionSource $rootSource)
- {
- $this->rootSource = $rootSource;
- }
-
- private function resolveSubDefinition(HasSubDefinition $definition, $currentIndex)
- {
- $subDefinitionName = $definition->getSubDefinitionName();
-
- if ($subDefinitionName === $definition->getName()) {
- // Extending itself: look in the next sources only (else infinite recursion)
- $subDefinition = $this->getDefinition($subDefinitionName, $currentIndex + 1);
- } else {
- // Extending another definition: look from the root
- $subDefinition = $this->rootSource->getDefinition($subDefinitionName);
- }
-
- if ($subDefinition) {
- $definition->setSubDefinition($subDefinition);
- }
- }
-
- public function setMutableDefinitionSource(MutableDefinitionSource $mutableSource)
- {
- $this->mutableSource = $mutableSource;
-
- array_unshift($this->sources, $mutableSource);
- }
-}
+++ /dev/null
-<?php
-/**
- * PHP-DI
- *
- * @link http://php-di.org/
- * @copyright Matthieu Napoli (http://mnapoli.fr/)
- * @license http://www.opensource.org/licenses/mit-license.php MIT (see the LICENSE file)
- */
-
-namespace DI\Definition;
-
-use DI\Scope;
-
-/**
- * Definition of a string composed of other strings.
- *
- * @since 5.0
- * @author Matthieu Napoli <matthieu@mnapoli.fr>
- */
-class StringDefinition implements Definition
-{
- /**
- * Entry name
- * @var string
- */
- private $name;
-
- /**
- * @var string
- */
- private $expression;
-
- /**
- * @param string $name Entry name
- * @param string $expression
- */
- public function __construct($name, $expression)
- {
- $this->name = $name;
- $this->expression = $expression;
- }
-
- /**
- * @return string Entry name
- */
- public function getName()
- {
- return $this->name;
- }
-
- /**
- * {@inheritdoc}
- */
- public function getScope()
- {
- return Scope::SINGLETON;
- }
-
- /**
- * @return string
- */
- public function getExpression()
- {
- return $this->expression;
- }
-}
+++ /dev/null
-<?php
-/**
- * PHP-DI
- *
- * @link http://php-di.org/
- * @copyright Matthieu Napoli (http://mnapoli.fr/)
- * @license http://www.opensource.org/licenses/mit-license.php MIT (see the LICENSE file)
- */
-
-namespace DI\Definition;
-
-use DI\Scope;
-
-/**
- * Definition of a value for dependency injection.
- *
- * @author Matthieu Napoli <matthieu@mnapoli.fr>
- */
-class ValueDefinition implements Definition
-{
- /**
- * Entry name
- * @var string
- */
- private $name;
-
- /**
- * @var mixed
- */
- private $value;
-
- /**
- * @param string $name Entry name
- * @param mixed $value
- */
- public function __construct($name, $value)
- {
- $this->name = $name;
- $this->value = $value;
- }
-
- /**
- * @return string Entry name
- */
- public function getName()
- {
- return $this->name;
- }
-
- /**
- * A value definition is like a constant, there is nothing to compute, the value is the same for everyone.
- *
- * {@inheritdoc}
- */
- public function getScope()
- {
- return Scope::SINGLETON;
- }
-
- /**
- * @return mixed
- */
- public function getValue()
- {
- return $this->value;
- }
-}
+++ /dev/null
-<?php
-/**
- * PHP-DI
- *
- * @link http://php-di.org/
- * @copyright Matthieu Napoli (http://mnapoli.fr/)
- * @license http://www.opensource.org/licenses/mit-license.php MIT (see the LICENSE file)
- */
-
-namespace DI;
-
-use Interop\Container\Exception\ContainerException;
-
-/**
- * Exception for the Container
- */
-class DependencyException extends \Exception implements ContainerException
-{
-}
+++ /dev/null
-<?php
-/**
- * PHP-DI
- *
- * @link http://php-di.org/
- * @copyright Matthieu Napoli (http://mnapoli.fr/)
- * @license http://www.opensource.org/licenses/mit-license.php MIT (see the LICENSE file)
- */
-
-namespace DI;
-
-/**
- * Describes the basic interface of a factory.
- *
- * @since 4.0
- * @author Matthieu Napoli <matthieu@mnapoli.fr>
- */
-interface FactoryInterface
-{
- /**
- * Resolves an entry by its name. If given a class name, it will return a new instance of that class.
- *
- * @param string $name Entry name or a class name.
- * @param array $parameters Optional parameters to use to build the entry. Use this to force specific
- * parameters to specific values. Parameters not defined in this array will
- * be automatically resolved.
- *
- * @throws \InvalidArgumentException The name parameter must be of type string.
- * @throws DependencyException Error while resolving the entry.
- * @throws NotFoundException No entry or class found for the given name.
- * @return mixed
- */
- public function make($name, array $parameters = []);
-}
+++ /dev/null
-<?php
-
-namespace DI\Invoker;
-
-use DI\Definition\Helper\DefinitionHelper;
-use DI\Definition\Resolver\DefinitionResolver;
-use Invoker\ParameterResolver\ParameterResolver;
-use ReflectionFunctionAbstract;
-
-/**
- * Resolves callable parameters using definitions.
- *
- * @since 5.0
- * @author Matthieu Napoli <matthieu@mnapoli.fr>
- */
-class DefinitionParameterResolver implements ParameterResolver
-{
- /**
- * @var DefinitionResolver
- */
- private $definitionResolver;
-
- public function __construct(DefinitionResolver $definitionResolver)
- {
- $this->definitionResolver = $definitionResolver;
- }
-
- /**
- * {@inheritdoc}
- */
- public function getParameters(
- ReflectionFunctionAbstract $reflection,
- array $providedParameters,
- array $resolvedParameters
- ) {
- // Skip parameters already resolved
- if (! empty($resolvedParameters)) {
- $providedParameters = array_diff_key($providedParameters, $resolvedParameters);
- }
-
- foreach ($providedParameters as $key => $value) {
- if (! $value instanceof DefinitionHelper) {
- continue;
- }
-
- $definition = $value->getDefinition('');
- $value = $this->definitionResolver->resolve($definition);
-
- if (is_int($key)) {
- // Indexed by position
- $resolvedParameters[$key] = $value;
- } else {
- // Indexed by parameter name
- // TODO optimize?
- $reflectionParameters = $reflection->getParameters();
- foreach ($reflectionParameters as $reflectionParameter) {
- if ($key === $reflectionParameter->name) {
- $resolvedParameters[$reflectionParameter->getPosition()] = $value;
- }
- }
- }
- }
-
- return $resolvedParameters;
- }
-}
+++ /dev/null
-<?php
-/**
- * PHP-DI
- *
- * @link http://php-di.org/
- * @copyright Matthieu Napoli (http://mnapoli.fr/)
- * @license http://www.opensource.org/licenses/mit-license.php MIT (see the LICENSE file)
- */
-
-namespace DI;
-
-/**
- * Invoke a callable.
- *
- * @author Matthieu Napoli <matthieu@mnapoli.fr>
- */
-interface InvokerInterface extends \Invoker\InvokerInterface
-{
-}
+++ /dev/null
-<?php
-/**
- * PHP-DI
- *
- * @link http://php-di.org/
- * @copyright Matthieu Napoli (http://mnapoli.fr/)
- * @license http://www.opensource.org/licenses/mit-license.php MIT (see the LICENSE file)
- */
-
-namespace DI;
-
-use Interop\Container\Exception\NotFoundException as BaseNotFoundException;
-
-/**
- * Exception thrown when a class or a value is not found in the container
- */
-class NotFoundException extends \Exception implements BaseNotFoundException
-{
-}
+++ /dev/null
-<?php
-/**
- * PHP-DI
- *
- * @link http://php-di.org/
- * @copyright Matthieu Napoli (http://mnapoli.fr/)
- * @license http://www.opensource.org/licenses/mit-license.php MIT (see the LICENSE file)
- */
-
-namespace DI\Proxy;
-
-use ProxyManager\Configuration;
-use ProxyManager\Factory\LazyLoadingValueHolderFactory;
-use ProxyManager\GeneratorStrategy\EvaluatingGeneratorStrategy;
-
-/**
- * Creates proxy classes.
- *
- * Wraps Ocramius/ProxyManager LazyLoadingValueHolderFactory.
- *
- * @see ProxyManager\Factory\LazyLoadingValueHolderFactory
- *
- * @since 5.0
- * @author Matthieu Napoli <matthieu@mnapoli.fr>
- */
-class ProxyFactory
-{
- /**
- * If true, write the proxies to disk to improve performances.
- * @var boolean
- */
- private $writeProxiesToFile;
-
- /**
- * Directory where to write the proxies (if $writeProxiesToFile is enabled).
- * @var string
- */
- private $proxyDirectory;
-
- /**
- * @var LazyLoadingValueHolderFactory|null
- */
- private $proxyManager;
-
- public function __construct($writeProxiesToFile, $proxyDirectory = null)
- {
- $this->writeProxiesToFile = $writeProxiesToFile;
- $this->proxyDirectory = $proxyDirectory;
- }
-
- /**
- * Creates a new lazy proxy instance of the given class with
- * the given initializer
- *
- * @param string $className name of the class to be proxied
- * @param \Closure $initializer initializer to be passed to the proxy
- *
- * @return \ProxyManager\Proxy\LazyLoadingInterface
- */
- public function createProxy($className, \Closure $initializer)
- {
- $this->createProxyManager();
-
- return $this->proxyManager->createProxy($className, $initializer);
- }
-
- private function createProxyManager()
- {
- if ($this->proxyManager !== null) {
- return;
- }
-
- if (! class_exists('ProxyManager\Configuration')) {
- throw new \RuntimeException('The ocramius/proxy-manager library is not installed. Lazy injection requires that library to be installed with Composer in order to work. Run "composer require ocramius/proxy-manager:~0.3".');
- }
-
- $config = new Configuration();
-
- if ($this->writeProxiesToFile) {
- $config->setProxiesTargetDir($this->proxyDirectory);
- spl_autoload_register($config->getProxyAutoloader());
- } else {
- $config->setGeneratorStrategy(new EvaluatingGeneratorStrategy());
- }
-
- $this->proxyManager = new LazyLoadingValueHolderFactory($config);
- }
-}
+++ /dev/null
-<?php
-/**
- * PHP-DI
- *
- * @link http://php-di.org/
- * @copyright Matthieu Napoli (http://mnapoli.fr/)
- * @license http://www.opensource.org/licenses/mit-license.php MIT (see the LICENSE file)
- */
-
-namespace DI\Reflection;
-
-/**
- * Create a reflection object from a callable.
- *
- * @author Matthieu Napoli <matthieu@mnapoli.fr>
- */
-class CallableReflectionFactory
-{
- /**
- * @param callable $callable
- *
- * @return \ReflectionFunctionAbstract
- */
- public static function fromCallable($callable)
- {
- // Array callable
- if (is_array($callable)) {
- list($class, $method) = $callable;
-
- return new \ReflectionMethod($class, $method);
- }
-
- // Closure
- if ($callable instanceof \Closure) {
- return new \ReflectionFunction($callable);
- }
-
- // Callable object (i.e. implementing __invoke())
- if (is_object($callable) && method_exists($callable, '__invoke')) {
- return new \ReflectionMethod($callable, '__invoke');
- }
-
- // Callable class (i.e. implementing __invoke())
- if (is_string($callable) && class_exists($callable) && method_exists($callable, '__invoke')) {
- return new \ReflectionMethod($callable, '__invoke');
- }
-
- // Standard function
- return new \ReflectionFunction($callable);
- }
-}
+++ /dev/null
-<?php
-/**
- * PHP-DI
- *
- * @link http://php-di.org/
- * @copyright Matthieu Napoli (http://mnapoli.fr/)
- * @license http://www.opensource.org/licenses/mit-license.php MIT (see the LICENSE file)
- */
-
-namespace DI;
-
-/**
- * Scope enum.
- *
- * The scope defines the lifecycle of an entry.
- *
- * @author Matthieu Napoli <matthieu@mnapoli.fr>
- */
-class Scope
-{
- /**
- * A singleton entry will be computed once and shared.
- *
- * For a class, only a single instance of the class will be created.
- */
- const SINGLETON = 'singleton';
-
- /**
- * A prototype entry will be recomputed each time it is asked.
- *
- * For a class, this will create a new instance each time.
- */
- const PROTOTYPE = 'prototype';
-
- /**
- * Method kept for backward compatibility, use the constant instead.
- *
- * @return string
- */
- public static function SINGLETON()
- {
- return self::SINGLETON;
- }
-
- /**
- * Method kept for backward compatibility, use the constant instead.
- *
- * @return string
- */
- public static function PROTOTYPE()
- {
- return self::PROTOTYPE;
- }
-}
+++ /dev/null
-<?php
-/**
- * PHP-DI
- *
- * @link http://php-di.org/
- * @copyright Matthieu Napoli (http://mnapoli.fr/)
- * @license http://www.opensource.org/licenses/mit-license.php MIT (see the LICENSE file)
- */
-
-namespace DI;
-
-use DI\Definition\EntryReference;
-use DI\Definition\Helper\ArrayDefinitionExtensionHelper;
-use DI\Definition\Helper\FactoryDefinitionHelper;
-use DI\Definition\Helper\ObjectDefinitionHelper;
-use DI\Definition\Helper\EnvironmentVariableDefinitionHelper;
-use DI\Definition\Helper\ValueDefinitionHelper;
-use DI\Definition\Helper\StringDefinitionHelper;
-
-if (! function_exists('DI\value')) {
- /**
- * Helper for defining an object.
- *
- * @param mixed $value
- *
- * @return ValueDefinitionHelper
- */
- function value($value)
- {
- return new ValueDefinitionHelper($value);
- }
-}
-
-if (! function_exists('DI\object')) {
- /**
- * Helper for defining an object.
- *
- * @param string|null $className Class name of the object.
- * If null, the name of the entry (in the container) will be used as class name.
- *
- * @return ObjectDefinitionHelper
- */
- function object($className = null)
- {
- return new ObjectDefinitionHelper($className);
- }
-}
-
-if (! function_exists('DI\factory')) {
- /**
- * Helper for defining a container entry using a factory function/callable.
- *
- * @param callable $factory The factory is a callable that takes the container as parameter
- * and returns the value to register in the container.
- *
- * @return FactoryDefinitionHelper
- */
- function factory($factory)
- {
- return new FactoryDefinitionHelper($factory);
- }
-}
-
-if (! function_exists('DI\decorate')) {
- /**
- * Decorate the previous definition using a callable.
- *
- * Example:
- *
- * 'foo' => decorate(function ($foo, $container) {
- * return new CachedFoo($foo, $container->get('cache'));
- * })
- *
- * @param callable $callable The callable takes the decorated object as first parameter and
- * the container as second.
- *
- * @return FactoryDefinitionHelper
- */
- function decorate($callable)
- {
- return new FactoryDefinitionHelper($callable, true);
- }
-}
-
-if (! function_exists('DI\get')) {
- /**
- * Helper for referencing another container entry in an object definition.
- *
- * @param string $entryName
- *
- * @return EntryReference
- */
- function get($entryName)
- {
- return new EntryReference($entryName);
- }
-}
-
-if (! function_exists('DI\link')) {
- /**
- * Helper for referencing another container entry in an object definition.
- *
- * @deprecated \DI\link() has been replaced by \DI\get()
- *
- * @param string $entryName
- *
- * @return EntryReference
- */
- function link($entryName)
- {
- return new EntryReference($entryName);
- }
-}
-
-if (! function_exists('DI\env')) {
- /**
- * Helper for referencing environment variables.
- *
- * @param string $variableName The name of the environment variable.
- * @param mixed $defaultValue The default value to be used if the environment variable is not defined.
- *
- * @return EnvironmentVariableDefinitionHelper
- */
- function env($variableName, $defaultValue = null)
- {
- // Only mark as optional if the default value was *explicitly* provided.
- $isOptional = 2 === func_num_args();
-
- return new EnvironmentVariableDefinitionHelper($variableName, $isOptional, $defaultValue);
- }
-}
-
-if (! function_exists('DI\add')) {
- /**
- * Helper for extending another definition.
- *
- * Example:
- *
- * 'log.backends' => DI\add(DI\get('My\Custom\LogBackend'))
- *
- * or:
- *
- * 'log.backends' => DI\add([
- * DI\get('My\Custom\LogBackend')
- * ])
- *
- * @param mixed|array $values A value or an array of values to add to the array.
- *
- * @return ArrayDefinitionExtensionHelper
- *
- * @since 5.0
- */
- function add($values)
- {
- if (! is_array($values)) {
- $values = [$values];
- }
-
- return new ArrayDefinitionExtensionHelper($values);
- }
-}
-
-if (! function_exists('DI\string')) {
- /**
- * Helper for concatenating strings.
- *
- * Example:
- *
- * 'log.filename' => DI\string('{app.path}/app.log')
- *
- * @param string $expression A string expression. Use the `{}` placeholders to reference other container entries.
- *
- * @return StringDefinitionHelper
- *
- * @since 5.0
- */
- function string($expression)
- {
- return new StringDefinitionHelper((string) $expression);
- }
-}
+++ /dev/null
-# .gitattributes
-tests/ export-ignore
-phpunit.xml.dist export-ignore
-.travis.yml export-ignore
-
-# Auto detect text files and perform LF normalization
-* text=auto
+++ /dev/null
-.DS_Store
-.idea/*
-vendor/*
-composer.phar
-composer.lock
+++ /dev/null
-Copyright (C) 2015 Matthieu Napoli
-
-Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
-associated documentation files (the "Software"), to deal in the Software without restriction,
-including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense,
-and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so,
-subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all copies or substantial
-portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT
-NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
-IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
-WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
-SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+++ /dev/null
-# PhpDocReader
-
-[![Build Status](https://img.shields.io/travis/PHP-DI/PhpDocReader.svg)](https://travis-ci.org/mnapoli/PhpDocReader)
-[![Coverage Status](https://img.shields.io/coveralls/PHP-DI/PhpDocReader.svg)](https://coveralls.io/r/mnapoli/PhpDocReader)
-![](https://img.shields.io/packagist/dt/PHP-DI/phpdoc-reader.svg)
-
-This project is used by:
-
-- [PHP-DI](http://php-di.org/)
-- [phockito-unit-php-di](https://github.com/balihoo/phockito-unit-php-di)
-
-Fork the README to add your project here.
-
-## Features
-
-PhpDocReader parses `@var` and `@param` values in PHP docblocks:
-
-```php
-
-use My\Cache\Backend;
-
-class Cache
-{
- /**
- * @var Backend
- */
- protected $backend;
-
- /**
- * @param Backend $backend
- */
- public function __construct($backend)
- {
- }
-}
-```
-
-It supports namespaced class names with the same resolution rules as PHP:
-
-- fully qualified name (starting with `\`)
-- imported class name (eg. `use My\Cache\Backend;`)
-- relative class name (from the current namespace, like `SubNamespace\MyClass`)
-- aliased class name (eg. `use My\Cache\Backend as FooBar;`)
-
-Primitive types (`@var string`) are ignored (returns null), only valid class names are returned.
-
-## Usage
-
-```php
-$reader = new PhpDocReader();
-
-// Read a property type (@var phpdoc)
-$property = new ReflectionProperty($className, $propertyName);
-$propertyClass = $reader->getPropertyClass($property);
-
-// Read a parameter type (@param phpdoc)
-$parameter = new ReflectionParameter(array($className, $methodName), $parameterName);
-$parameterClass = $reader->getParameterClass($parameter);
-```
+++ /dev/null
-{
- "name": "php-di/phpdoc-reader",
- "type": "library",
- "description": "PhpDocReader parses @var and @param values in PHP docblocks (supports namespaced class names with the same resolution rules as PHP)",
- "keywords": ["phpdoc", "reflection"],
- "license": "MIT",
- "autoload": {
- "psr-4": {
- "PhpDocReader\\": "src/PhpDocReader"
- }
- },
- "autoload-dev": {
- "psr-4": {
- "UnitTest\\PhpDocReader\\": "tests/"
- }
- },
- "require": {
- "php": ">=5.3.0"
- },
- "require-dev": {
- "phpunit/phpunit": "~4.6"
- }
-}
+++ /dev/null
-<?php
-
-namespace PhpDocReader;
-
-/**
- * @author Matthieu Napoli <matthieu@mnapoli.fr>
- */
-class AnnotationException extends \Exception
-{
-}
+++ /dev/null
-<?php
-
-namespace PhpDocReader;
-
-use PhpDocReader\PhpParser\UseStatementParser;
-use ReflectionParameter;
-use ReflectionProperty;
-
-/**
- * PhpDoc reader
- *
- * @author Matthieu Napoli <matthieu@mnapoli.fr>
- */
-class PhpDocReader
-{
- /**
- * @var UseStatementParser
- */
- private $parser;
-
- private $ignoredTypes = array(
- 'bool',
- 'boolean',
- 'string',
- 'int',
- 'integer',
- 'float',
- 'double',
- 'array',
- 'object',
- 'callable',
- 'resource',
- );
-
- /**
- * Enable or disable throwing errors when PhpDoc Errors occur (when parsing annotations)
- *
- * @var bool
- */
- private $ignorePhpDocErrors;
-
- /**
- *
- * @param bool $ignorePhpDocErrors
- */
- public function __construct($ignorePhpDocErrors = false)
- {
- $this->parser = new UseStatementParser();
- $this->ignorePhpDocErrors = $ignorePhpDocErrors;
- }
-
- /**
- * Parse the docblock of the property to get the class of the var annotation.
- *
- * @param ReflectionProperty $property
- *
- * @throws AnnotationException
- * @return string|null Type of the property (content of var annotation)
- *
- * @deprecated Use getPropertyClass instead.
- */
- public function getPropertyType(ReflectionProperty $property)
- {
- return $this->getPropertyClass($property);
- }
-
- /**
- * Parse the docblock of the property to get the class of the var annotation.
- *
- * @param ReflectionProperty $property
- *
- * @throws AnnotationException
- * @return string|null Type of the property (content of var annotation)
- */
- public function getPropertyClass(ReflectionProperty $property)
- {
- // Get the content of the @var annotation
- if (preg_match('/@var\s+([^\s]+)/', $property->getDocComment(), $matches)) {
- list(, $type) = $matches;
- } else {
- return null;
- }
-
- // Ignore primitive types
- if (in_array($type, $this->ignoredTypes)) {
- return null;
- }
-
- // Ignore types containing special characters ([], <> ...)
- if (! preg_match('/^[a-zA-Z0-9\\\\_]+$/', $type)) {
- return null;
- }
-
- $class = $property->getDeclaringClass();
-
- // If the class name is not fully qualified (i.e. doesn't start with a \)
- if ($type[0] !== '\\') {
- $alias = (false === $pos = strpos($type, '\\')) ? $type : substr($type, 0, $pos);
- $loweredAlias = strtolower($alias);
-
- // Retrieve "use" statements
- $uses = $this->parser->parseUseStatements($property->getDeclaringClass());
-
- $found = false;
-
- if (isset($uses[$loweredAlias])) {
- // Imported classes
- if (false !== $pos) {
- $type = $uses[$loweredAlias] . substr($type, $pos);
- } else {
- $type = $uses[$loweredAlias];
- }
- $found = true;
- } elseif ($this->classExists($class->getNamespaceName() . '\\' . $type)) {
- $type = $class->getNamespaceName() . '\\' . $type;
- $found = true;
- } elseif (isset($uses['__NAMESPACE__']) && $this->classExists($uses['__NAMESPACE__'] . '\\' . $type)) {
- // Class namespace
- $type = $uses['__NAMESPACE__'] . '\\' . $type;
- $found = true;
- } elseif ($this->classExists($type)) {
- // No namespace
- $found = true;
- }
-
- if (!$found && !$this->ignorePhpDocErrors) {
- throw new AnnotationException(sprintf(
- 'The @var annotation on %s::%s contains a non existent class "%s". '
- . 'Did you maybe forget to add a "use" statement for this annotation?',
- $class->name,
- $property->getName(),
- $type
- ));
- }
- }
-
- if (!$this->classExists($type) && !$this->ignorePhpDocErrors) {
- throw new AnnotationException(sprintf(
- 'The @var annotation on %s::%s contains a non existent class "%s"',
- $class->name,
- $property->getName(),
- $type
- ));
- }
-
- // Remove the leading \ (FQN shouldn't contain it)
- $type = ltrim($type, '\\');
-
- return $type;
- }
-
- /**
- * Parse the docblock of the property to get the class of the param annotation.
- *
- * @param ReflectionParameter $parameter
- *
- * @throws AnnotationException
- * @return string|null Type of the property (content of var annotation)
- *
- * @deprecated Use getParameterClass instead.
- */
- public function getParameterType(ReflectionParameter $parameter)
- {
- return $this->getParameterClass($parameter);
- }
-
- /**
- * Parse the docblock of the property to get the class of the param annotation.
- *
- * @param ReflectionParameter $parameter
- *
- * @throws AnnotationException
- * @return string|null Type of the property (content of var annotation)
- */
- public function getParameterClass(ReflectionParameter $parameter)
- {
- // Use reflection
- $parameterClass = $parameter->getClass();
- if ($parameterClass !== null) {
- return $parameterClass->name;
- }
-
- $parameterName = $parameter->name;
- // Get the content of the @param annotation
- $method = $parameter->getDeclaringFunction();
- if (preg_match('/@param\s+([^\s]+)\s+\$' . $parameterName . '/', $method->getDocComment(), $matches)) {
- list(, $type) = $matches;
- } else {
- return null;
- }
-
- // Ignore primitive types
- if (in_array($type, $this->ignoredTypes)) {
- return null;
- }
-
- // Ignore types containing special characters ([], <> ...)
- if (! preg_match('/^[a-zA-Z0-9\\\\_]+$/', $type)) {
- return null;
- }
-
- $class = $parameter->getDeclaringClass();
-
- // If the class name is not fully qualified (i.e. doesn't start with a \)
- if ($type[0] !== '\\') {
- $alias = (false === $pos = strpos($type, '\\')) ? $type : substr($type, 0, $pos);
- $loweredAlias = strtolower($alias);
-
- // Retrieve "use" statements
- $uses = $this->parser->parseUseStatements($class);
-
- $found = false;
-
- if (isset($uses[$loweredAlias])) {
- // Imported classes
- if (false !== $pos) {
- $type = $uses[$loweredAlias] . substr($type, $pos);
- } else {
- $type = $uses[$loweredAlias];
- }
- $found = true;
- } elseif ($this->classExists($class->getNamespaceName() . '\\' . $type)) {
- $type = $class->getNamespaceName() . '\\' . $type;
- $found = true;
- } elseif (isset($uses['__NAMESPACE__']) && $this->classExists($uses['__NAMESPACE__'] . '\\' . $type)) {
- // Class namespace
- $type = $uses['__NAMESPACE__'] . '\\' . $type;
- $found = true;
- } elseif ($this->classExists($type)) {
- // No namespace
- $found = true;
- }
-
- if (!$found && !$this->ignorePhpDocErrors) {
- throw new AnnotationException(sprintf(
- 'The @param annotation for parameter "%s" of %s::%s contains a non existent class "%s". '
- . 'Did you maybe forget to add a "use" statement for this annotation?',
- $parameterName,
- $class->name,
- $method->name,
- $type
- ));
- }
- }
-
- if (!$this->classExists($type) && !$this->ignorePhpDocErrors) {
- throw new AnnotationException(sprintf(
- 'The @param annotation for parameter "%s" of %s::%s contains a non existent class "%s"',
- $parameterName,
- $class->name,
- $method->name,
- $type
- ));
- }
-
- // Remove the leading \ (FQN shouldn't contain it)
- $type = ltrim($type, '\\');
-
- return $type;
- }
-
- /**
- * @param string $class
- * @return bool
- */
- private function classExists($class)
- {
- return class_exists($class) || interface_exists($class);
- }
-}
+++ /dev/null
-<?php
-
-namespace PhpDocReader\PhpParser;
-
-/**
- * Parses a file for namespaces/use/class declarations.
- *
- * Class taken and adapted from doctrine/annotations to avoid pulling the whole package.
- *
- * @author Fabien Potencier <fabien@symfony.com>
- * @author Christian Kaps <christian.kaps@mohiva.com>
- */
-class TokenParser
-{
- /**
- * The token list.
- *
- * @var array
- */
- private $tokens;
-
- /**
- * The number of tokens.
- *
- * @var int
- */
- private $numTokens;
-
- /**
- * The current array pointer.
- *
- * @var int
- */
- private $pointer = 0;
-
- /**
- * @param string $contents
- */
- public function __construct($contents)
- {
- $this->tokens = token_get_all($contents);
-
- // The PHP parser sets internal compiler globals for certain things. Annoyingly, the last docblock comment it
- // saw gets stored in doc_comment. When it comes to compile the next thing to be include()d this stored
- // doc_comment becomes owned by the first thing the compiler sees in the file that it considers might have a
- // docblock. If the first thing in the file is a class without a doc block this would cause calls to
- // getDocBlock() on said class to return our long lost doc_comment. Argh.
- // To workaround, cause the parser to parse an empty docblock. Sure getDocBlock() will return this, but at least
- // it's harmless to us.
- token_get_all("<?php\n/**\n *\n */");
-
- $this->numTokens = count($this->tokens);
- }
-
- /**
- * Gets all use statements.
- *
- * @param string $namespaceName The namespace name of the reflected class.
- *
- * @return array A list with all found use statements.
- */
- public function parseUseStatements($namespaceName)
- {
- $statements = array();
- while (($token = $this->next())) {
- if ($token[0] === T_USE) {
- $statements = array_merge($statements, $this->parseUseStatement());
- continue;
- }
- if ($token[0] !== T_NAMESPACE || $this->parseNamespace() != $namespaceName) {
- continue;
- }
-
- // Get fresh array for new namespace. This is to prevent the parser to collect the use statements
- // for a previous namespace with the same name. This is the case if a namespace is defined twice
- // or if a namespace with the same name is commented out.
- $statements = array();
- }
-
- return $statements;
- }
-
- /**
- * Gets the next non whitespace and non comment token.
- *
- * @param boolean $docCommentIsComment If TRUE then a doc comment is considered a comment and skipped.
- * If FALSE then only whitespace and normal comments are skipped.
- *
- * @return array|null The token if exists, null otherwise.
- */
- private function next($docCommentIsComment = true)
- {
- for ($i = $this->pointer; $i < $this->numTokens; $i++) {
- $this->pointer++;
- if ($this->tokens[$i][0] === T_WHITESPACE ||
- $this->tokens[$i][0] === T_COMMENT ||
- ($docCommentIsComment && $this->tokens[$i][0] === T_DOC_COMMENT)) {
-
- continue;
- }
-
- return $this->tokens[$i];
- }
-
- return null;
- }
-
- /**
- * Parses a single use statement.
- *
- * @return array A list with all found class names for a use statement.
- */
- private function parseUseStatement()
- {
- $class = '';
- $alias = '';
- $statements = array();
- $explicitAlias = false;
- while (($token = $this->next())) {
- $isNameToken = $token[0] === T_STRING || $token[0] === T_NS_SEPARATOR;
- if (!$explicitAlias && $isNameToken) {
- $class .= $token[1];
- $alias = $token[1];
- } elseif ($explicitAlias && $isNameToken) {
- $alias .= $token[1];
- } elseif ($token[0] === T_AS) {
- $explicitAlias = true;
- $alias = '';
- } elseif ($token === ',') {
- $statements[strtolower($alias)] = $class;
- $class = '';
- $alias = '';
- $explicitAlias = false;
- } elseif ($token === ';') {
- $statements[strtolower($alias)] = $class;
- break;
- } else {
- break;
- }
- }
-
- return $statements;
- }
-
- /**
- * Gets the namespace.
- *
- * @return string The found namespace.
- */
- private function parseNamespace()
- {
- $name = '';
- while (($token = $this->next()) && ($token[0] === T_STRING || $token[0] === T_NS_SEPARATOR)) {
- $name .= $token[1];
- }
-
- return $name;
- }
-}
+++ /dev/null
-<?php
-
-namespace PhpDocReader\PhpParser;
-
-use SplFileObject;
-
-/**
- * Parses a file for "use" declarations.
- *
- * Class taken and adapted from doctrine/annotations to avoid pulling the whole package.
- *
- * @author Fabien Potencier <fabien@symfony.com>
- * @author Christian Kaps <christian.kaps@mohiva.com>
- */
-class UseStatementParser
-{
- /**
- * @return array A list with use statements in the form (Alias => FQN).
- */
- public function parseUseStatements(\ReflectionClass $class)
- {
- if (false === $filename = $class->getFilename()) {
- return array();
- }
-
- $content = $this->getFileContent($filename, $class->getStartLine());
-
- if (null === $content) {
- return array();
- }
-
- $namespace = preg_quote($class->getNamespaceName());
- $content = preg_replace('/^.*?(\bnamespace\s+' . $namespace . '\s*[;{].*)$/s', '\\1', $content);
- $tokenizer = new TokenParser('<?php ' . $content);
-
- $statements = $tokenizer->parseUseStatements($class->getNamespaceName());
-
- return $statements;
- }
-
- /**
- * Gets the content of the file right up to the given line number.
- *
- * @param string $filename The name of the file to load.
- * @param integer $lineNumber The number of lines to read from file.
- *
- * @return string The content of the file.
- */
- private function getFileContent($filename, $lineNumber)
- {
- if ( ! is_file($filename)) {
- return null;
- }
-
- $content = '';
- $lineCnt = 0;
- $file = new SplFileObject($filename);
- while (!$file->eof()) {
- if ($lineCnt++ == $lineNumber) {
- break;
- }
-
- $content .= $file->fgets();
- }
-
- return $content;
- }
-}
* @category Community Framework
*/
class ApplicationHandler extends SingletonFactory {
- /**
- * @var ApplicationCacheBuilder
- */
- protected $applicationCacheBuilder;
/**
* application cache
* @var array<array>
*/
protected $pageURLs = array();
- /**
- * ApplicationHandler constructor.
- *
- * @param ApplicationCacheBuilder $applicationCacheBuilder
- */
- public function __construct(ApplicationCacheBuilder $applicationCacheBuilder) {
- $this->applicationCacheBuilder = $applicationCacheBuilder;
-
- parent::__construct();
- }
-
/**
* Initializes cache.
*/
protected function init() {
- $this->cache = $this->applicationCacheBuilder->getData();
+ $this->cache = ApplicationCacheBuilder::getInstance()->getData();
}
/**
<?php
namespace wcf\system\event;
+use wcf\data\event\listener\EventListener;
use wcf\system\cache\builder\EventListenerCacheBuilder;
use wcf\system\event\listener\IParameterizedEventListener;
use wcf\system\event\IEventListener as ILegacyEventListener;
*/
protected $actions = null;
- /**
- * @var EventListenerCacheBuilder
- */
- protected $eventListenerCacheBuilder;
-
/**
* registered inherit actions
* @var array
*/
protected $listenerObjects = [];
- /**
- * EventHandler constructor.
- *
- * @param EventListenerCacheBuilder $eventListenerCacheBuilder
- */
- public function __construct(EventListenerCacheBuilder $eventListenerCacheBuilder) {
- $this->eventListenerCacheBuilder = $eventListenerCacheBuilder;
-
- parent::__construct();
- }
-
/**
* Loads all registered actions of the active package.
*/
protected function loadActions() {
$environment = ((class_exists('wcf\system\WCFACP', false) || class_exists('wcf\system\CLIWCF', false)) ? 'admin' : 'user');
- $cache = $this->eventListenerCacheBuilder->getData();
+ $cache = EventListenerCacheBuilder::getInstance()->getData();
if (isset($cache['actions'][$environment])) {
$this->actions = $cache['actions'][$environment];
if (isset($this->inheritedActions[$member])) {
$actions = $this->inheritedActions[$member];
if (isset($actions[$eventName]) && !empty($actions[$eventName])) {
+ /** @var EventListener $eventListener */
foreach ($actions[$eventName] as $eventListener) {
if ($eventListener->validateOptions() && $eventListener->validatePermissions()) {
if (isset($this->inheritedActionsObjects[$name][$eventListener->listenerClassName])) continue;
}
$this->actionsObjects[$name] = [];
+ /** @var EventListener $eventListener */
foreach ($this->actions[$name] as $eventListener) {
if ($eventListener->validateOptions() && $eventListener->validatePermissions()) {
if (isset($this->actionsObjects[$name][$eventListener->listenerClassName])) continue;
use wcf\system\html\input\filter\IHtmlInputFilter;
use wcf\system\html\input\filter\MessageHtmlInputFilter;
use wcf\system\html\input\node\HtmlInputNodeProcessor;
-use wcf\system\WCF;
class HtmlInputProcessor {
/**
/**
* @return IHtmlInputFilter|MessageHtmlInputFilter
- * @throws \DI\NotFoundException
*/
public function getHtmlInputFilter() {
if ($this->htmlInputFilter === null) {
- $this->htmlInputFilter = WCF::getDIContainer()->make(MessageHtmlInputFilter::class);
+ $this->htmlInputFilter = new MessageHtmlInputFilter();
}
return $this->htmlInputFilter;
/**
* @return HtmlInputNodeProcessor
- * @throws \DI\NotFoundException
*/
public function getHtmlInputNodeProcessor() {
if ($this->htmlInputNodeProcessor === null) {
- $this->htmlInputNodeProcessor = WCF::getDIContainer()->make(HtmlInputNodeProcessor::class);
+ $this->htmlInputNodeProcessor = new HtmlInputNodeProcessor();
}
return $this->htmlInputNodeProcessor;
namespace wcf\system\html\input\node;
use wcf\system\html\node\HtmlNodeProcessor;
-use wcf\system\WCF;
class HtmlInputNodeProcessor extends HtmlNodeProcessor {
public function load($html) {
}
public function process() {
- $woltlabMention = WCF::getDIContainer()->get(HtmlInputNodeWoltlabMention::class);
+ $woltlabMention = new HtmlInputNodeWoltlabMention();
$woltlabMention->process($this);
}
}
<?php
namespace wcf\system\html\input\node;
-use wcf\system\message\embedded\object\MessageEmbeddedObjectManager;
-
class HtmlInputNodeWoltlabMention implements IHtmlInputNode {
- /**
- * @var MessageEmbeddedObjectManager
- */
- protected $messageEmbeddedObjectManager;
-
- public function __construct(MessageEmbeddedObjectManager $messageEmbeddedObjectManager) {
- $this->messageEmbeddedObjectManager = $messageEmbeddedObjectManager;
- }
-
public function process(HtmlInputNodeProcessor $htmlInputNodeProcessor) {
$userIds = [];
use wcf\system\html\output\node\HtmlOutputNodeBlockquote;
use wcf\system\html\output\node\HtmlOutputNodeWoltlabMention;
use wcf\system\html\output\node\IHtmlOutputNode;
-use wcf\system\WCF;
class HtmlOutputNodeProcessor extends HtmlNodeProcessor {
protected $nodeData = [];
public function process() {
// TODO: this should be dynamic to some extent
- $quoteNode = WCF::getDIContainer()->get(HtmlOutputNodeBlockquote::class);
+ $quoteNode = new HtmlOutputNodeBlockquote();
$quoteNode->process($this);
- $woltlabMentionNode = WCF::getDIContainer()->get(HtmlOutputNodeWoltlabMention::class);
+ $woltlabMentionNode = new HtmlOutputNodeWoltlabMention();
$woltlabMentionNode->process($this);
}
use wcf\util\StringUtil;
class HtmlOutputNodeBlockquote implements IHtmlOutputNode {
- /**
- * @var ApplicationHandler
- */
- protected $applicationHandler;
-
- public function __construct(ApplicationHandler $applicationHandler) {
- $this->applicationHandler = $applicationHandler;
- }
-
public function process(HtmlOutputNodeProcessor $htmlOutputNodeProcessor) {
$elements = $htmlOutputNodeProcessor->getDocument()->getElementsByTagName('blockquote');
while ($elements->length) {
}
public function replaceTag(array $data) {
- $externalQuoteLink = (!empty($data['url'])) ? !$this->applicationHandler->isInternalURL($data['url']) : false;
+ $externalQuoteLink = (!empty($data['url'])) ? !ApplicationHandler::getInstance()->isInternalURL($data['url']) : false;
if (!$externalQuoteLink) {
$data['url'] = preg_replace('~^https://~', RouteHandler::getProtocol(), $data['url']);
}
use wcf\data\user\UserProfileCache;
use wcf\system\application\ApplicationHandler;
use wcf\system\html\output\HtmlOutputNodeProcessor;
-use wcf\system\request\RouteHandler;
use wcf\system\WCF;
use wcf\util\StringUtil;
class HtmlOutputNodeWoltlabMention implements IHtmlOutputNode {
- /**
- * @var ApplicationHandler
- */
- protected $applicationHandler;
-
/**
* @var UserProfile[]
*/
protected $userProfiles;
- /**
- * @var UserProfileCache
- */
- protected $userProfileCache;
-
- public function __construct(ApplicationHandler $applicationHandler, UserProfileCache $userProfileCache) {
- $this->applicationHandler = $applicationHandler;
- $this->userProfileCache = $userProfileCache;
- }
-
public function process(HtmlOutputNodeProcessor $htmlOutputNodeProcessor) {
$this->userProfiles = [];
}
if (!empty($userIds)) {
- $this->userProfiles = $this->userProfileCache->getUserProfiles($userIds);
+ $this->userProfiles = UserProfileCache::getInstance()->getUserProfiles($userIds);
}
}
<?php
namespace wcf\system\request;
use wcf\system\exception\SystemException;
+use wcf\system\SingletonFactory;
/**
* Resolves incoming requests and performs lookups for controller to url mappings.
* @subpackage system.request
* @category Community Framework
*/
-class ControllerMap {
+class ControllerMap extends SingletonFactory {
/**
* list of <ControllerName> to <controller-name> mappings
* @var array<string>
*/
protected $lookupCache = [];
- public function __construct() {
+ protected function init() {
// TODO: initialize custom controller mappings
}
* @category Community Framework
*/
class LinkHandler extends SingletonFactory {
- /**
- * @var ApplicationHandler
- */
- protected $applicationHandler;
-
- /**
- * @var RequestHandler
- */
- protected $requestHandler;
-
- /**
- * @var RouteHandler
- */
- protected $routeHandler;
-
/**
* regex object to filter title
* @var \wcf\system\RegEx
*/
protected $titleReplace = array();
- /**
- * LinkHandler constructor.
- *
- * @param ApplicationHandler $applicationHandler
- * @param RequestHandler $requestHandler
- * @param RouteHandler $routeHandler
- */
- public function __construct(ApplicationHandler $applicationHandler, RequestHandler $requestHandler, RouteHandler $routeHandler) {
- $this->applicationHandler = $applicationHandler;
- $this->requestHandler = $requestHandler;
- $this->routeHandler = $routeHandler;
-
- parent::__construct();
- }
/**
* @see \wcf\system\SingletonFactory::init()
public function getLink($controller = null, array $parameters = array(), $url = '') {
$abbreviation = 'wcf';
$anchor = '';
- $isACP = $originIsACP = $this->requestHandler->isACPRequest();
+ $isACP = $originIsACP = RequestHandler::getInstance()->isACPRequest();
$forceWCF = $isRaw = false;
$appendSession = $encodeTitle = true;
$controller = 'Index';
}
else {
- // loading the PageMenu object as a dependency in ACP requests breaks everything
- return WCF::getDIContainer()->get(PageMenu::class)->getLandingPage()->getProcessor()->getLink();
+ return PageMenu::getInstance()->getLandingPage()->getProcessor()->getLink();
}
}
}
$parameters['controller'] = $controller;
- $routeURL = $this->routeHandler->buildRoute($parameters, $isACP);
+ $routeURL = RouteHandler::getInstance()->buildRoute($parameters, $isACP);
if (!$isRaw && !empty($url)) {
$routeURL .= (strpos($routeURL, '?') === false) ? '?' : '&';
}
$url = RouteHandler::getHost() . RouteHandler::getPath(array('acp')) . ($isACP ? 'acp/' : '') . $url;
}
else {
- if ($this->requestHandler->inRescueMode()) {
+ if (RequestHandler::getInstance()->inRescueMode()) {
$pageURL = RouteHandler::getHost() . str_replace('//', '/', RouteHandler::getPath(array('acp')));
}
else {
// try to resolve abbreviation
$application = null;
if ($abbreviation != 'wcf') {
- $application = $this->applicationHandler->getApplication($abbreviation);
+ $application = ApplicationHandler::getInstance()->getApplication($abbreviation);
}
// fallback to primary application if abbreviation is 'wcf' or unknown
if ($forceWCF) {
- $application = $this->applicationHandler->getWCF();
+ $application = ApplicationHandler::getInstance()->getWCF();
}
else if ($application === null) {
- $application = $this->applicationHandler->getPrimaryApplication();
+ $application = ApplicationHandler::getInstance()->getPrimaryApplication();
}
$pageURL = $application->getPageURL();
*/
protected $activeRequest = null;
- /**
- * @var ApplicationHandler
- */
- protected $applicationHandler;
-
- /**
- * @var ControllerMap
- */
- protected $controllerMap;
-
/**
* true, if current domain mismatch any known domain
* @var boolean
*/
protected $isACPRequest = false;
- /**
- * @var RouteHandler
- */
- protected $routeHandler;
-
- /**
- * RequestHandler constructor.
- *
- * @param ApplicationHandler $applicationHandler
- * @param ControllerMap $controllerMap
- * @param RouteHandler $routeHandler
- */
- public function __construct(ApplicationHandler $applicationHandler, ControllerMap $controllerMap, RouteHandler $routeHandler) {
- $this->applicationHandler = $applicationHandler;
- $this->controllerMap = $controllerMap;
- $this->routeHandler = $routeHandler;
-
- parent::__construct();
- }
-
/**
* @see \wcf\system\SingletonFactory::init()
*/
protected function init() {
if (isset($_SERVER['HTTP_HOST'])) {
- foreach ($this->applicationHandler->getApplications() as $application) {
+ foreach (ApplicationHandler::getInstance()->getApplications() as $application) {
if ($application->domainName == $_SERVER['HTTP_HOST']) {
$this->inRescueMode = false;
break;
// check if WCF is running as standalone
if ($this->inRescueMode() && PACKAGE_ID == 1) {
- if ($this->applicationHandler->getWCF()->domainName == $_SERVER['HTTP_HOST']) {
+ if (ApplicationHandler::getInstance()->getWCF()->domainName == $_SERVER['HTTP_HOST']) {
$this->inRescueMode = false;
}
}
public function handle($application = 'wcf', $isACPRequest = false) {
$this->isACPRequest = $isACPRequest;
- // initialize route handler
- $this->routeHandler->setRequestHandler($this);
- $this->routeHandler->setDefaultRoutes();
-
- if (!$this->routeHandler->matches($application)) {
+ if (!RouteHandler::getInstance()->matches($application)) {
if (ENABLE_DEBUG_MODE) {
throw new SystemException("Cannot handle request, no valid route provided.");
}
*/
protected function buildRequest($application) {
try {
- $routeData = $this->routeHandler->getRouteData();
+ $routeData = RouteHandler::getInstance()->getRouteData();
// handle landing page for frontend requests
if (!$this->isACPRequest()) {
// check if accessing from the wrong domain (e.g. "www." omitted but domain was configured with)
if (!defined('WCF_RUN_MODE') || WCF_RUN_MODE != 'embedded') {
- $applicationObject = $this->applicationHandler->getApplication($application);
+ $applicationObject = ApplicationHandler::getInstance()->getApplication($application);
if ($applicationObject->domainName != $_SERVER['HTTP_HOST']) {
// build URL, e.g. http://example.net/forum/
$url = FileUtil::addTrailingSlash(RouteHandler::getProtocol() . $applicationObject->domainName . RouteHandler::getPath());
$controller = $routeData['controller'];
- $classData = $this->controllerMap->resolve($application, $controller, $this->isACPRequest());
+ $classData = ControllerMap::getInstance()->resolve($application, $controller, $this->isACPRequest());
// check if controller was provided exactly as it should
/*
* @param array $routeData
*/
protected function handleDefaultController($application, array &$routeData) {
- if (!$this->routeHandler->isDefaultController()) {
+ if (!RouteHandler::getInstance()->isDefaultController()) {
return;
}
- // loading the PageMenu object as a dependency in ACP requests breaks everything
- $landingPage = WCF::getDIContainer()->get(PageMenu::class)->getLandingPage();
+ $landingPage = PageMenu::getInstance()->getLandingPage();
if ($landingPage === null) {
return;
}
// resolve implicit application abbreviation for landing page controller
$landingPageApplication = $landingPage->getApplication();
- $primaryApplication = $this->applicationHandler->getPrimaryApplication();
- $primaryApplicationAbbr = $this->applicationHandler->getAbbreviation($primaryApplication->packageID);
+ $primaryApplication = ApplicationHandler::getInstance()->getPrimaryApplication();
+ $primaryApplicationAbbr = ApplicationHandler::getInstance()->getAbbreviation($primaryApplication->packageID);
if ($landingPageApplication == 'wcf') {
$landingPageApplication = $primaryApplicationAbbr;
}
// check if currently invoked application matches the landing page
if ($landingPageApplication == $application) {
$routeData['controller'] = $landingPage->getController();
- $routeData['controller'] = $this->controllerMap->lookup($routeData['controller']);
+ $routeData['controller'] = ControllerMap::getInstance()->lookup($routeData['controller']);
return;
}
}
// set default controller
- $applicationObj = WCF::getApplicationObject($this->applicationHandler->getApplication($application));
+ $applicationObj = WCF::getApplicationObject(ApplicationHandler::getInstance()->getApplication($application));
$routeData['controller'] = preg_replace('~^.*?\\\([^\\\]+)(?:Action|Form|Page)$~', '\\1', $applicationObj->getPrimaryController());
- $routeData['controller'] = $this->controllerMap->lookup($routeData['controller']);
+ $routeData['controller'] = ControllerMap::getInstance()->lookup($routeData['controller']);
}
/**
*/
protected static $secure = null;
- /**
- * @var ApplicationHandler
- */
- protected $applicationHandler;
-
/**
* list of application abbreviation and default controller name
* @var array<string>
*/
protected $defaultControllers = null;
- /**
- * @var EventHandler
- */
- protected $eventHandler;
-
/**
* true, if default controller is used (support for custom landing page)
* @var boolean
*/
protected $isDefaultController = false;
- /**
- * @var RequestHandler
- */
- protected $requestHandler;
-
/**
* list of available routes
* @var IRoute[]
*/
protected $routeData = null;
- /**
- * RouteHandler constructor.
- *
- * @param ApplicationHandler $applicationHandler
- * @param EventHandler $eventHandler
- */
- public function __construct(ApplicationHandler $applicationHandler, EventHandler $eventHandler) {
- $this->applicationHandler = $applicationHandler;
- $this->eventHandler = $eventHandler;
-
- parent::__construct();
- }
-
/**
* Sets default routes.
*/
- public function setDefaultRoutes() {
- $route = WCF::getDIContainer()->make(DynamicRequestRoute::class);
+ protected function init() {
+ $route = new DynamicRequestRoute();
$route->setIsACP(true);
$this->addRoute($route);
- $route = WCF::getDIContainer()->make(DynamicRequestRoute::class);
+ $route = new DynamicRequestRoute();
$route->setIsACP(false);
$this->addRoute($route);
// fire event
- $this->eventHandler->fireAction($this, 'didInit');
- }
-
- /**
- * Sets the required request handler, setter function to avoid circular dependencies.
- *
- * @param RequestHandler $requestHandler
- */
- public function setRequestHandler(RequestHandler $requestHandler) {
- $this->requestHandler = $requestHandler;
+ EventHandler::getInstance()->fireAction($this, 'didInit');
}
/**
public static function getPathInfo() {
if (self::$pathInfo === null) {
self::$pathInfo = '';
- $requestHandler = WCF::getDIContainer()->get(RequestHandler::class);
- if (!URL_LEGACY_MODE || $requestHandler->isACPRequest()) {
+ if (!URL_LEGACY_MODE || RequestHandler::getInstance()->isACPRequest()) {
// WCF 2.1: ?Foo/Bar/
if (!empty($_SERVER['QUERY_STRING'])) {
// don't use parse_str as it replaces dots with underscores
}
// WCF 2.0: index.php/Foo/Bar/
- if ((URL_LEGACY_MODE && !$requestHandler->isACPRequest()) || ($requestHandler->isACPRequest() && empty(self::$pathInfo))) {
+ if ((URL_LEGACY_MODE && !RequestHandler::getInstance()->isACPRequest()) || (RequestHandler::getInstance()->isACPRequest() && empty(self::$pathInfo))) {
if (isset($_SERVER['PATH_INFO'])) {
self::$pathInfo = $_SERVER['PATH_INFO'];
}
if ($this->defaultControllers === null) {
$this->defaultControllers = array();
- foreach ($this->applicationHandler->getApplications() as $application) {
+ foreach (ApplicationHandler::getInstance()->getApplications() as $application) {
$app = WCF::getApplicationObject($application);
if (!$app) {
use wcf\system\request\ControllerMap;
use wcf\system\request\RequestHandler;
use wcf\system\request\RouteHandler;
-use wcf\system\WCF;
/**
* Dynamic route implementation to resolve HTTP requests, handling controllers using a distinct pattern.
* @category Community Framework
*/
class DynamicRequestRoute implements IRequestRoute {
- /**
- * @var ApplicationHandler
- */
- protected $applicationHandler;
-
/**
* schema for outgoing links
* @var array<array>
*/
protected $buildSchema = [];
- /**
- * @var ControllerMap
- */
- protected $controllerMap;
-
/**
* route is restricted to ACP
* @var boolean
*/
protected $primaryApplication = '';
- /**
- * @var RequestHandler
- */
- protected $requestHandler;
-
/**
* list of required components
* @var array<string>
*/
protected $routeData = [];
- /**
- * @var RouteHandler;
- */
- protected $routeHandler;
-
- /**
- * DynamicRequestRoute constructor.
- *
- * @param ApplicationHandler $applicationHandler
- * @param ControllerMap $controllerMap
- * @param RequestHandler $requestHandler
- * @param RouteHandler $routeHandler
- */
- public function __construct(ApplicationHandler $applicationHandler, ControllerMap $controllerMap, RequestHandler $requestHandler, RouteHandler $routeHandler) {
- $this->applicationHandler = $applicationHandler;
- $this->controllerMap = $controllerMap;
- $this->requestHandler = $requestHandler;
- $this->routeHandler = $routeHandler;
-
- $this->init();
- }
-
/**
* Sets default routing information.
*/
$buildSchema = ltrim($buildSchema, '/');
$components = preg_split('~({(?:[a-z]+)})~', $buildSchema, -1, PREG_SPLIT_DELIM_CAPTURE | PREG_SPLIT_NO_EMPTY);
- $delimiters = ['/', '-', '.', '_'];
foreach ($components as $component) {
$type = 'component';
if (count($components) == 1 && isset($components['controller'])) {
$ignoreController = false;
- if (!$this->requestHandler->isACPRequest()) {
- // loading the PageMenu object as a dependency in ACP requests breaks everything
- $landingPage = WCF::getDIContainer()->get(PageMenu::class)->getLandingPage();
+ if (!RequestHandler::getInstance()->isACPRequest()) {
+ $landingPage = PageMenu::getInstance()->getLandingPage();
if ($this->primaryApplication === '') {
- $primaryApplication = $this->applicationHandler->getPrimaryApplication();
- $this->primaryApplication = $this->applicationHandler->getAbbreviation($primaryApplication->packageID);
+ $primaryApplication = ApplicationHandler::getInstance()->getPrimaryApplication();
+ $this->primaryApplication = ApplicationHandler::getInstance()->getAbbreviation($primaryApplication->packageID);
}
// check if this is the default controller
- if (strcasecmp($this->routeHandler->getDefaultController($application), $components['controller']) === 0) {
+ if (strcasecmp(RouteHandler::getInstance()->getDefaultController($application), $components['controller']) === 0) {
// check if this matches the primary application
if ($this->primaryApplication === $application) {
if (strcasecmp($landingPage->getController(), $components['controller']) === 0) {
/**
* @see IRoute::matches()
*/
- public function matches($requestURL) {
+ public function matches($application, $requestURL) {
if (preg_match($this->pattern, $requestURL, $matches)) {
foreach ($matches as $key => $value) {
if (!is_numeric($key)) {
* @return string
*/
protected function getControllerName($application, $controller) {
- return $this->controllerMap->lookup($controller);
+ return ControllerMap::getInstance()->lookup($controller);
}
}
use wcf\util\FileUtil;
class LookupRequestRoute implements IRequestRoute {
- /**
- * @var ControllerMap
- */
- protected $controllerMap;
-
protected $routeData = [];
- public function __construct(ControllerMap $controllerMap) {
- $this->controllerMap = $controllerMap;
- }
-
/**
* @inheritDoc
*/
if (preg_match($regex, $requestURL, $matches)) {
if (!empty($matches['id'])) {
// check for static controller URLs
- $this->routeData = $this->controllerMap->resolveCustomController($application, $matches['controller']);
+ $this->routeData = ControllerMap::getInstance()->resolveCustomController($application, $matches['controller']);
}
if (empty($this->routeData)) {
// try to match the entire url
- $this->routeData = $this->controllerMap->resolveCustomController($application, $requestURL);
+ $this->routeData = ControllerMap::getInstance()->resolveCustomController($application, $requestURL);
}
}
<?php
namespace wcf\system\request\route;
-use wcf\system\application\ApplicationHandler;
-use wcf\system\menu\page\PageMenu;
use wcf\system\request\ControllerMap;
-use wcf\system\request\RequestHandler;
-use wcf\system\request\RouteHandler;
/**
* Static route implementation to resolve HTTP requests, handling a single controller.
* @category Community Framework
*/
class StaticRequestRoute extends DynamicRequestRoute {
- /**
- * @var \wcf\system\request\ControllerMap
- */
- protected $controllerMap;
-
/**
* static application identifier
* @var string
*/
protected $staticController = '';
- /**
- * StaticRequestRoute constructor.
- *
- * @param \wcf\system\application\ApplicationHandler $applicationHandler
- * @param \wcf\system\request\ControllerMap $controllerMap
- * @param \wcf\system\menu\page\PageMenu $pageMenu
- * @param \wcf\system\request\RequestHandler $requestHandler
- * @param \wcf\system\request\RouteHandler $routeHandler
- */
- public function __construct(ApplicationHandler $applicationHandler, ControllerMap $controllerMap, PageMenu $pageMenu, RequestHandler $requestHandler, RouteHandler $routeHandler) {
- parent::__construct($applicationHandler, $pageMenu, $requestHandler, $routeHandler);
-
- $this->controllerMap = $controllerMap;
- }
-
/**
* @see \wcf\system\request\route\IRequestRoute::setIsACP()
*/
/**
* @see \wcf\system\request\IRoute::matches()
*/
- public function matches($requestURL) {
- if (parent::matches($requestURL)) {
+ public function matches($application, $requestURL) {
+ if (parent::matches($application, $requestURL)) {
$this->routeData['application'] = $this->staticApplication;
- $this->routeData['controller'] = $this->controllerMap->lookup($this->staticController);
+ $this->routeData['controller'] = ControllerMap::getInstance()->lookup($this->staticController);
$this->routeData['isDefaultController'] = false;
return true;
* @category Community Framework
*/
class ACPSessionFactory {
- /**
- * @var EventHandler
- */
- protected $eventHandler;
-
/**
* session editor class name
* @var string
*/
protected $sessionEditor = 'wcf\data\acp\session\ACPSessionEditor';
- /**
- * @var SessionHandler
- */
- protected $sessionHandler;
-
- /**
- * ACPSessionFactory constructor.
- *
- * @param EventHandler $eventHandler
- * @param SessionHandler $sessionHandler
- */
- public function __construct(EventHandler $eventHandler, SessionHandler $sessionHandler) {
- $this->eventHandler = $eventHandler;
- $this->sessionHandler = $sessionHandler;
- }
-
/**
* Loads the object of the active session.
*/
public function load() {
// get session
$sessionID = $this->readSessionID();
- $this->sessionHandler->load($this->sessionEditor, $sessionID);
+ SessionHandler::getInstance()->load($this->sessionEditor, $sessionID);
// call beforeInit event
if (!defined('NO_IMPORTS')) {
- $this->eventHandler->fireAction($this, 'beforeInit');
+ EventHandler::getInstance()->fireAction($this, 'beforeInit');
}
$this->init();
// call afterInit event
if (!defined('NO_IMPORTS')) {
- $this->eventHandler->fireAction($this, 'afterInit');
+ EventHandler::getInstance()->fireAction($this, 'afterInit');
}
}
* Initializes the session system.
*/
protected function init() {
- $this->sessionHandler->initSession();
+ SessionHandler::getInstance()->initSession();
}
/**
'requestMethod' => $this->requestMethod,
'lastActivityTime' => TIME_NOW
);
- /*if (!class_exists('wcf\system\CLIWCF', false) && PACKAGE_ID && RequestHandler::getInstance()->getActiveRequest() && RequestHandler::getInstance()->getActiveRequest()->getRequestObject() instanceof ITrackablePage && RequestHandler::getInstance()->getActiveRequest()->getRequestObject()->isTracked()) {
+ if (!class_exists('wcf\system\CLIWCF', false) && PACKAGE_ID && RequestHandler::getInstance()->getActiveRequest() && RequestHandler::getInstance()->getActiveRequest()->getRequestObject() instanceof ITrackablePage && RequestHandler::getInstance()->getActiveRequest()->getRequestObject()->isTracked()) {
$data['controller'] = RequestHandler::getInstance()->getActiveRequest()->getRequestObject()->getController();
$data['parentObjectType'] = RequestHandler::getInstance()->getActiveRequest()->getRequestObject()->getParentObjectType();
$data['parentObjectID'] = RequestHandler::getInstance()->getActiveRequest()->getRequestObject()->getParentObjectID();
$data['objectType'] = RequestHandler::getInstance()->getActiveRequest()->getRequestObject()->getObjectType();
$data['objectID'] = RequestHandler::getInstance()->getActiveRequest()->getRequestObject()->getObjectID();
- }*/
+ }
if ($this->variablesChanged) {
$data['sessionVariables'] = serialize($this->variables);
}