diff --git a/core/lib/Drupal/Core/DependencyInjection/Dumper/DebugPhpArrayDumper.php b/core/lib/Drupal/Core/DependencyInjection/Dumper/DebugPhpArrayDumper.php deleted file mode 100644 index fd1304a..0000000 --- a/core/lib/Drupal/Core/DependencyInjection/Dumper/DebugPhpArrayDumper.php +++ /dev/null @@ -1,67 +0,0 @@ - $value) { - if (is_array($value)) { - $code[$key] = $this->dumpCollection($value); - } - else { - $code[$key] = $this->dumpValue($value); - } - } - - return $code; - } - - /** - * {@inheritdoc} - */ - protected function getServiceCall($id, $invalid_behavior = ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE) { - if ($invalid_behavior !== ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE) { - return '@?' . $id; - } - - return '@' . $id; - } - - /** - * {@inheritdoc} - */ - protected function getParameterCall($name) { - return '%' . $name . '%'; - } - - /** - * {@inheritdoc} - */ - protected function getMachineFormat() { - return FALSE; - } - -} diff --git a/core/lib/Drupal/Core/DependencyInjection/Dumper/OptimizedPhpArrayDumper.php b/core/lib/Drupal/Core/DependencyInjection/Dumper/OptimizedPhpArrayDumper.php new file mode 100644 index 0000000..241e531 --- /dev/null +++ b/core/lib/Drupal/Core/DependencyInjection/Dumper/OptimizedPhpArrayDumper.php @@ -0,0 +1,496 @@ +getArray()); + } + + /** + * Returns the service container as a PHP array. + * + * @return array + * A PHP array representation of the service container. + */ + public function getArray() { + $definition = array(); + $definition['aliases'] = $this->getAliases(); + $definition['parameters'] = $this->getParameters(); + $definition['services'] = $this->getServiceDefinitions(); + $definition['machine_format'] = $this->getMachineFormat(); + return $definition; + } + + /** + * Returns the aliases as a PHP array. + * + * @return array + * The aliases. + */ + protected function getAliases() { + $alias_definitions = array(); + + $aliases = $this->container->getAliases(); + foreach ($aliases as $alias => $id) { + $id = (string) $id; + while (isset($aliases[$id])) { + $id = (string) $aliases[$id]; + } + $alias_definitions[$alias] = $id; + } + + return $alias_definitions; + } + + /** + * Returns parameters of the container as a PHP array. + * + * @return array + * The escaped and prepared parameters of the container. + */ + protected function getParameters() { + if (!$this->container->getParameterBag()->all()) { + return array(); + } + + $parameters = $this->container->getParameterBag()->all(); + $is_frozen = $this->container->isFrozen(); + return $this->prepareParameters($parameters, $is_frozen); + } + + /** + * Returns services of the container as a PHP array. + * + * @return array + * The service definitions. + */ + protected function getServiceDefinitions() { + if (!$this->container->getDefinitions()) { + return array(); + } + + $services = array(); + foreach ($this->container->getDefinitions() as $id => $definition) { + if ($definition->isPublic()) { + $services[$id] = serialize($this->getServiceDefinition($definition)); + } + } + + return $services; + } + + /** + * Prepares parameters for the PHP array dumping. + * + * @param array $parameters + * An array of parameters. + * + * @param bool $escape + * Whether keys with '%' should be escaped or not. + * + * @return array + */ + protected function prepareParameters($parameters, $escape = true) { + $filtered = array(); + foreach ($parameters as $key => $value) { + if (is_array($value)) { + $value = $this->prepareParameters($value, $escape); + } + elseif ($value instanceof Reference) { + $value = $this->dumpValue($value); + } + + $filtered[$key] = $value; + } + + return $escape ? $this->escape($filtered) : $filtered; + } + + /** + * Escapes parameters. + * + * @param array $parameters + * The parameters to escape for '%' characters. + * + * @return array + * The escaped parameters. + */ + protected function escape($parameters) { + $args = array(); + + foreach ($parameters as $key => $value) { + if (is_array($value)) { + $args[$key] = $this->escape($value); + } + elseif (is_string($value)) { + $args[$key] = str_replace('%', '%%', $value); + } + else { + $args[$key] = $value; + } + } + + return $args; + } + + /** + * Gets a service definition as PHP array. + * + * @param \Symfony\Component\DependencyInjection\Definition $definition + * The definition to process. + * + * @return array + * The service definition as PHP array. + */ + protected function getServiceDefinition($definition) { + $service = array(); + if ($definition->getClass()) { + $service['class'] = $definition->getClass(); + } + + if (!$definition->isPublic()) { + $service['public'] = FALSE; + } + + if ($definition->getFile()) { + $service['file'] = $definition->getFile(); + } + + if ($definition->isSynthetic()) { + $service['synthetic'] = TRUE; + } + + if ($definition->isLazy()) { + $service['lazy'] = TRUE; + } + + if ($definition->getArguments()) { + $arguments = $definition->getArguments(); + $service['arguments'] = $this->dumpCollection($arguments); + $service['arguments_count'] = count($arguments); + } + else { + $service['arguments_count'] = 0; + } + + if ($definition->getProperties()) { + $service['properties'] = $this->dumpCollection($definition->getProperties()); + } + + if ($definition->getMethodCalls()) { + $service['calls'] = $this->dumpMethodCalls($definition->getMethodCalls()); + } + + if (($scope = $definition->getScope()) !== ContainerInterface::SCOPE_CONTAINER) { + if ($scope === ContainerInterface::SCOPE_PROTOTYPE) { + // Scope prototype has been replaced with 'shared' => FALSE. + // This is a Symfony 2.8 forward compatibility fix. + // Reference: https://github.com/symfony/symfony/blob/2.8/UPGRADE-2.8.md#dependencyinjection + $service['shared'] = FALSE; + } + else { + throw new InvalidArgumentException("The 'scope' definition is deprecated in Symfony 3.0 and not supported by Drupal 8."); + } + } + + if (($decorated = $definition->getDecoratedService()) !== NULL) { + throw new InvalidArgumentException("The 'decorated' definition is not supported by the Drupal 8 run-time container. The Container Builder should have resolved that during the DecoratorServicePass compiler pass."); + } + + if ($callable = $definition->getFactory()) { + $service['factory'] = $this->dumpCallable($callable); + } + + if ($callable = $definition->getConfigurator()) { + $service['configurator'] = $this->dumpCallable($callable); + } + + return $service; + } + + /** + * Dumps method calls to a PHP array. + * + * @param array $calls + * An array of method calls. + * + * @return array + * The PHP array representation of the method calls. + */ + protected function dumpMethodCalls($calls) { + $code = array(); + + foreach ($calls as $key => $call) { + $method = $call[0]; + $arguments = array(); + if (!empty($call[1])) { + $arguments = $this->dumpCollection($call[1]); + } + + $code[$key] = [$method, $arguments]; + } + + return $code; + } + + + /** + * Dumps a collection to a PHP array. + * + * @param mixed $collection + * A collection to process. + * @param bool &$resolve + * Used for passing the information to the caller whether the given + * collection needed to be resolved or not. This is used for optimizing + * deep arrays that don't need to be traversed. + * + * @return \stdClass|array + * The collection in a suitable format. + */ + protected function dumpCollection($collection, &$resolve = FALSE) { + $code = array(); + + foreach ($collection as $key => $value) { + if (is_array($value)) { + $resolve_collection = FALSE; + $code[$key] = $this->dumpCollection($value, $resolve_collection); + + if ($resolve_collection) { + $resolve = TRUE; + } + } + else { + if (is_object($value)) { + $resolve = TRUE; + } + $code[$key] = $this->dumpValue($value); + } + } + + if (!$resolve) { + return $collection; + } + + return (object) array( + 'type' => 'collection', + 'value' => $code, + 'resolve' => $resolve, + ); + } + + /** + * Dumps callable to a PHP array. + * + * @param callable $callable + * The callable to process. + * + * @return callable + * The processed callable. + */ + protected function dumpCallable($callable) { + if (is_array($callable)) { + $callable[0] = $this->dumpValue($callable[0]); + $callable = array($callable[0], $callable[1]); + } + + return $callable; + } + + /** + * Returns a private service definition in a suitable format. + * + * @param string $id + * The ID of the service to get a private definition for. + * @param \Symfony\Component\DependencyInjection\Definition $definition + * The definition to process. + * @param bool $shared + * (optional) Whether the service will be shared with others. Default: FALSE + * + * @return \stdClass + * A very lightweight private service value object. + */ + protected function getPrivateServiceCall($id, Definition $definition, $shared = FALSE) { + $service_definition = $this->getServiceDefinition($definition); + if (!$id) { + $hash = sha1(serialize($service_definition)); + $id = 'private__' . $hash; + } + return (object) array( + 'type' => 'private_service', + 'id' => $id, + 'value' => $service_definition, + 'shared' => $shared, + ); + } + + /** + * Dumps the value to PHP array format. + * + * @param mixed $value + * The value to dump. + * + * @return mixed + * The dumped value in a suitable format. + * + * @throws RuntimeException When trying to dump object or resource + */ + protected function dumpValue($value) { + if (is_array($value)) { + $code = array(); + foreach ($value as $k => $v) { + $code[$k] = $this->dumpValue($v); + } + + return $code; + } + elseif ($value instanceof Reference) { + return $this->getReferenceCall((string) $value, $value); + } + elseif ($value instanceof Definition) { + return $this->getPrivateServiceCall(NULL, $value); + } + elseif ($value instanceof Parameter) { + return $this->getParameterCall((string) $value); + } + elseif ($value instanceof Expression) { + return $this->getExpressionCall((string) $value); + } + elseif (is_object($value)) { + // Drupal specific: Instantiated objects have a _serviceId parameter. + if (isset($value->_serviceId)) { + return $this->getReferenceCall($value->_serviceId); + } + throw new RuntimeException('Unable to dump a service container if a parameter is an object without _serviceId.'); + } + elseif (is_resource($value)) { + throw new RuntimeException('Unable to dump a service container if a parameter is a resource.'); + } + + return $value; + } + + /** + * Returns a service reference in a suitable PHP array format. + * + * @param string $id + * The ID of the service to get a reference for. + * @param \Symfony\Component\DependencyInjection\Reference $reference + * (optional) The reference object to process, needed to get the invalid + * behavior. + * + * @return string|\stdClass + * A suitable representation of the servie reference. + */ + protected function getReferenceCall($id, Reference $reference = NULL) { + $invalid_behavior = ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE; + + if ($reference !== NULL) { + $invalid_behavior = $reference->getInvalidBehavior(); + } + + // Private shared service. + $definition = $this->container->getDefinition($id); + if (!$definition->isPublic()) { + // The ContainerBuilder does not share a private service, + // but this means a new service is instantiated every time. + // Use a private shared service to circumvent the problem. + return $this->getPrivateServiceCall($id, $definition, TRUE); + } + + return $this->getServiceCall($id, $invalid_behavior); + } + + /** + * Returns a service reference in a suitable PHP array format. + * + * @param string $id + * The ID of the service to get a reference for. + * @param int $invalid_behavior + * (optional) The invalid behavior of the service. + * + * @return string|\stdClass + * A suitable representation of the servie reference. + */ + protected function getServiceCall($id, $invalid_behavior = ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE) { + return (object) array( + 'type' => 'service', + 'id' => $id, + 'invalidBehavior' => $invalid_behavior, + ); + } + + /** + * Dumps a parameter to PHP array format. + * + * @param string $name + * The name of the parameter to dump. + * + * @return string|\stdClass + * A suitable representation of the parameter reference. + */ + protected function getParameterCall($name) { + return (object) array( + 'type' => 'parameter', + 'name' => $name, + ); + } + + /** + * The expression to dump to PHP array format. + * + * @param string $expression + * The expression to dump. + * + * @throws RuntimeException When trying to dump an expression. + */ + protected function getExpressionCall($expression) { + throw new RuntimeException('Unable to use expressions as the Symfony ExpressionLanguage component is not installed.'); + } + + /** + * Whether this supports the machine format or not. + * + * @return bool + * TRUE if this supports machine format, FALSE otherwise. + */ + protected function getMachineFormat() { + return TRUE; + } + +} diff --git a/core/lib/Drupal/Core/DependencyInjection/Dumper/PhpArrayDumper.php b/core/lib/Drupal/Core/DependencyInjection/Dumper/PhpArrayDumper.php index 2bdd9aa..d4fc388 100644 --- a/core/lib/Drupal/Core/DependencyInjection/Dumper/PhpArrayDumper.php +++ b/core/lib/Drupal/Core/DependencyInjection/Dumper/PhpArrayDumper.php @@ -2,495 +2,68 @@ /** * @file - * Contains \Drupal\Core\DependencyInjection\Dumper + * Contains \Drupal\Core\DependencyInjection\Dumper\PhpArrayDumper. */ namespace Drupal\Core\DependencyInjection\Dumper; -use Symfony\Component\DependencyInjection\Alias; use Symfony\Component\DependencyInjection\ContainerInterface; -use Symfony\Component\DependencyInjection\Definition; -use Symfony\Component\DependencyInjection\Parameter; -use Symfony\Component\DependencyInjection\Reference; -use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException; -use Symfony\Component\DependencyInjection\Exception\RuntimeException; -use Symfony\Component\DependencyInjection\Dumper\Dumper; -use Symfony\Component\ExpressionLanguage\Expression; /** - * PhpArrayDumper dumps a service container as a serialized PHP array. + * DebugPhpArrayDumper dumps a service container as a human readable serialized + * PHP array. * - * The format of this dumper is very similar to the ContainerBuilder based - * format, but based on PHP arrays and \stdClass objects instead of rich value - * objects for performance reasons. + * The format of this dumper is very similar to the YAML based format, but + * based on PHP arrays instead of YAML strings. * - * By removing the abstraction and optimizing some cases like deep collections, - * less classes need to be loaded, less function calls need to be executed and - * less run time checks need to be made. + * It is human readable, for a machine optimized version based on this one see + * \Drupal\Core\DependencyInjection\Dumper\OptimizedPhpArrayDumper. * - * It is machine readable, for a human readable version based on this one see - * \Drupal\Core\DependencyInjection\Dumper\DebugPhpArrayDumper. - * - * @see \Drupal\Core\DependecyInjection\Container + * @see \Drupal\Core\DependencyInjection\PhpArrayContainer */ -class PhpArrayDumper extends Dumper { +class PhpArrayDumper extends OptimizedPhpArrayDumper { /** * {@inheritdoc} */ - public function dump(array $options = array()) { - return serialize($this->getArray()); - } - - /** - * Returns the service container as a PHP array. - * - * @return array - * A PHP array representation of the service container. - */ - public function getArray() { - $definition = array(); - $definition['aliases'] = $this->getAliases(); - $definition['parameters'] = $this->getParameters(); - $definition['services'] = $this->getServiceDefinitions(); - $definition['machine_format'] = $this->getMachineFormat(); - return $definition; - } - - /** - * Returns the aliases as a PHP array. - * - * @return array - * The aliases. - */ - protected function getAliases() { - $alias_definitions = array(); - - $aliases = $this->container->getAliases(); - foreach ($aliases as $alias => $id) { - $id = (string) $id; - while (isset($aliases[$id])) { - $id = (string) $aliases[$id]; - } - $alias_definitions[$alias] = $id; - } - - return $alias_definitions; - } - - /** - * Returns parameters of the container as a PHP array. - * - * @return array - * The escaped and prepared parameters of the container. - */ - protected function getParameters() { - if (!$this->container->getParameterBag()->all()) { - return array(); - } - - $parameters = $this->container->getParameterBag()->all(); - $is_frozen = $this->container->isFrozen(); - return $this->prepareParameters($parameters, $is_frozen); - } - - /** - * Returns services of the container as a PHP array. - * - * @return array - * The service definitions. - */ - protected function getServiceDefinitions() { - if (!$this->container->getDefinitions()) { - return array(); - } - - $services = array(); - foreach ($this->container->getDefinitions() as $id => $definition) { - if ($definition->isPublic()) { - $services[$id] = serialize($this->getServiceDefinition($definition)); - } - } - - return $services; - } - - /** - * Prepares parameters for the PHP array dumping. - * - * @param array $parameters - * An array of parameters. - * - * @param bool $escape - * Whether keys with '%' should be escaped or not. - * - * @return array - */ - protected function prepareParameters($parameters, $escape = true) { - $filtered = array(); - foreach ($parameters as $key => $value) { - if (is_array($value)) { - $value = $this->prepareParameters($value, $escape); - } - elseif ($value instanceof Reference) { - $value = $this->dumpValue($value); - } - - $filtered[$key] = $value; - } - - return $escape ? $this->escape($filtered) : $filtered; - } - - /** - * Escapes parameters. - * - * @param array $parameters - * The parameters to escape for '%' characters. - * - * @return array - * The escaped parameters. - */ - protected function escape($parameters) { - $args = array(); - - foreach ($parameters as $key => $value) { - if (is_array($value)) { - $args[$key] = $this->escape($value); - } - elseif (is_string($value)) { - $args[$key] = str_replace('%', '%%', $value); - } - else { - $args[$key] = $value; - } - } - - return $args; - } - - /** - * Gets a service definition as PHP array. - * - * @param \Symfony\Component\DependencyInjection\Definition $definition - * The definition to process. - * - * @return array - * The service definition as PHP array. - */ - protected function getServiceDefinition($definition) { - $service = array(); - if ($definition->getClass()) { - $service['class'] = $definition->getClass(); - } - - if (!$definition->isPublic()) { - $service['public'] = FALSE; - } - - if ($definition->getFile()) { - $service['file'] = $definition->getFile(); - } - - if ($definition->isSynthetic()) { - $service['synthetic'] = TRUE; - } - - if ($definition->isLazy()) { - $service['lazy'] = TRUE; - } - - if ($definition->getArguments()) { - $arguments = $definition->getArguments(); - $service['arguments'] = $this->dumpCollection($arguments); - $service['arguments_count'] = count($arguments); - } - else { - $service['arguments_count'] = 0; - } - - if ($definition->getProperties()) { - $service['properties'] = $this->dumpCollection($definition->getProperties()); - } - - if ($definition->getMethodCalls()) { - $service['calls'] = $this->dumpMethodCalls($definition->getMethodCalls()); - } - - if (($scope = $definition->getScope()) !== ContainerInterface::SCOPE_CONTAINER) { - if ($scope === ContainerInterface::SCOPE_PROTOTYPE) { - // Scope prototype has been replaced with 'shared' => FALSE. - // This is a Symfony 2.8 forward compatibility fix. - // Reference: https://github.com/symfony/symfony/blob/2.8/UPGRADE-2.8.md#dependencyinjection - $service['shared'] = FALSE; - } - else { - throw new InvalidArgumentException("The 'scope' definition is deprecated in Symfony 3.0 and not supported by Drupal 8."); - } - } - - if (($decorated = $definition->getDecoratedService()) !== NULL) { - throw new InvalidArgumentException("The 'decorated' definition is not supported by the Drupal 8 run-time container. The Container Builder should have resolved that during the DecoratorServicePass compiler pass."); - } - - if ($callable = $definition->getFactory()) { - $service['factory'] = $this->dumpCallable($callable); - } - - if ($callable = $definition->getConfigurator()) { - $service['configurator'] = $this->dumpCallable($callable); - } - - return $service; - } - - /** - * Dumps method calls to a PHP array. - * - * @param array $calls - * An array of method calls. - * - * @return array - * The PHP array representation of the method calls. - */ - protected function dumpMethodCalls($calls) { - $code = array(); - - foreach ($calls as $key => $call) { - $method = $call[0]; - $arguments = array(); - if (!empty($call[1])) { - $arguments = $this->dumpCollection($call[1]); - } - - $code[$key] = [$method, $arguments]; - } - - return $code; - } - - - /** - * Dumps a collection to a PHP array. - * - * @param mixed $collection - * A collection to process. - * @param bool &$resolve - * Used for passing the information to the caller whether the given - * collection needed to be resolved or not. This is used for optimizing - * deep arrays that don't need to be traversed. - * - * @return \stdClass|array - * The collection in a suitable format. - */ protected function dumpCollection($collection, &$resolve = FALSE) { - $code = array(); + $code = array(); foreach ($collection as $key => $value) { if (is_array($value)) { - $resolve_collection = FALSE; - $code[$key] = $this->dumpCollection($value, $resolve_collection); - - if ($resolve_collection) { - $resolve = TRUE; - } + $code[$key] = $this->dumpCollection($value); } else { - if (is_object($value)) { - $resolve = TRUE; - } $code[$key] = $this->dumpValue($value); } } - if (!$resolve) { - return $collection; - } - - return (object) array( - 'type' => 'collection', - 'value' => $code, - 'resolve' => $resolve, - ); - } - - /** - * Dumps callable to a PHP array. - * - * @param callable $callable - * The callable to process. - * - * @return callable - * The processed callable. - */ - protected function dumpCallable($callable) { - if (is_array($callable)) { - $callable[0] = $this->dumpValue($callable[0]); - $callable = array($callable[0], $callable[1]); - } - - return $callable; - } - - /** - * Returns a private service definition in a suitable format. - * - * @param string $id - * The ID of the service to get a private definition for. - * @param \Symfony\Component\DependencyInjection\Definition $definition - * The definition to process. - * @param bool $shared - * (optional) Whether the service will be shared with others. Default: FALSE - * - * @return \stdClass - * A very lightweight private service value object. - */ - protected function getPrivateServiceCall($id, Definition $definition, $shared = FALSE) { - $service_definition = $this->getServiceDefinition($definition); - if (!$id) { - $hash = sha1(serialize($service_definition)); - $id = 'private__' . $hash; - } - return (object) array( - 'type' => 'private_service', - 'id' => $id, - 'value' => $service_definition, - 'shared' => $shared, - ); - } - - /** - * Dumps the value to PHP array format. - * - * @param mixed $value - * The value to dump. - * - * @return mixed - * The dumped value in a suitable format. - * - * @throws RuntimeException When trying to dump object or resource - */ - protected function dumpValue($value) { - if (is_array($value)) { - $code = array(); - foreach ($value as $k => $v) { - $code[$k] = $this->dumpValue($v); - } - - return $code; - } - elseif ($value instanceof Reference) { - return $this->getReferenceCall((string) $value, $value); - } - elseif ($value instanceof Definition) { - return $this->getPrivateServiceCall(NULL, $value); - } - elseif ($value instanceof Parameter) { - return $this->getParameterCall((string) $value); - } - elseif ($value instanceof Expression) { - return $this->getExpressionCall((string) $value); - } - elseif (is_object($value)) { - // Drupal specific: Instantiated objects have a _serviceId parameter. - if (isset($value->_serviceId)) { - return $this->getReferenceCall($value->_serviceId); - } - throw new RuntimeException('Unable to dump a service container if a parameter is an object without _serviceId.'); - } - elseif (is_resource($value)) { - throw new RuntimeException('Unable to dump a service container if a parameter is a resource.'); - } - - return $value; + return $code; } /** - * Returns a service reference in a suitable PHP array format. - * - * @param string $id - * The ID of the service to get a reference for. - * @param \Symfony\Component\DependencyInjection\Reference $reference - * (optional) The reference object to process, needed to get the invalid - * behavior. - * - * @return string|\stdClass - * A suitable representation of the servie reference. + * {@inheritdoc} */ - protected function getReferenceCall($id, Reference $reference = NULL) { - $invalid_behavior = ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE; - - if ($reference !== NULL) { - $invalid_behavior = $reference->getInvalidBehavior(); - } - - // Private shared service. - $definition = $this->container->getDefinition($id); - if (!$definition->isPublic()) { - // The ContainerBuilder does not share a private service, - // but this means a new service is instantiated every time. - // Use a private shared service to circumvent the problem. - return $this->getPrivateServiceCall($id, $definition, TRUE); + protected function getServiceCall($id, $invalid_behavior = ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE) { + if ($invalid_behavior !== ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE) { + return '@?' . $id; } - return $this->getServiceCall($id, $invalid_behavior); + return '@' . $id; } /** - * Returns a service reference in a suitable PHP array format. - * - * @param string $id - * The ID of the service to get a reference for. - * @param int $invalid_behavior - * (optional) The invalid behavior of the service. - * - * @return string|\stdClass - * A suitable representation of the servie reference. - */ - protected function getServiceCall($id, $invalid_behavior = ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE) { - return (object) array( - 'type' => 'service', - 'id' => $id, - 'invalidBehavior' => $invalid_behavior, - ); - } - - /** - * Dumps a parameter to PHP array format. - * - * @param string $name - * The name of the parameter to dump. - * - * @return string|\stdClass - * A suitable representation of the parameter reference. + * {@inheritdoc} */ protected function getParameterCall($name) { - return (object) array( - 'type' => 'parameter', - 'name' => $name, - ); - } - - /** - * The expression to dump to PHP array format. - * - * @param string $expression - * The expression to dump. - * - * @throws RuntimeException When trying to dump an expression. - */ - protected function getExpressionCall($expression) { - throw new RuntimeException('Unable to use expressions as the Symfony ExpressionLanguage component is not installed.'); + return '%' . $name . '%'; } /** - * Whether this supports the machine format or not. - * - * @return bool - * TRUE if this supports machine format, FALSE otherwise. + * {@inheritdoc} */ protected function getMachineFormat() { - return TRUE; + return FALSE; } } diff --git a/core/lib/Drupal/Core/DependencyInjection/BootstrapContainer.php b/core/lib/Drupal/Core/DependencyInjection/PhpArrayContainer.php similarity index 98% rename from core/lib/Drupal/Core/DependencyInjection/BootstrapContainer.php rename to core/lib/Drupal/Core/DependencyInjection/PhpArrayContainer.php index f5f2b9d..f0848aa 100644 --- a/core/lib/Drupal/Core/DependencyInjection/BootstrapContainer.php +++ b/core/lib/Drupal/Core/DependencyInjection/PhpArrayContainer.php @@ -1,7 +1,7 @@ machineFormat = TRUE; + $this->containerClass = '\Drupal\Core\DependencyInjection\Container'; + $this->containerDefinition = $this->getMockContainerDefinition(); + $this->container = new $this->containerClass($this->containerDefinition, TRUE); + } + + /** + * Tests that passing a non-supported format throws an InvalidArgumentException. + * @covers ::__construct + * + * @expectedException \Symfony\Component\DependencyInjection\Exception\InvalidArgumentException + */ + public function test_construct() { + $container_definition = $this->getMockContainerDefinition(); + $container_definition['machine_format'] = !$this->machineFormat; + $container = new $this->containerClass($container_definition, TRUE); + } + + + /** + * Tests that Container::getParameter() works properly. + * @covers ::getParameter + */ + public function test_getParameter() { + $this->assertEquals($this->containerDefinition['parameters']['some_config'], $this->container->getParameter('some_config'), 'Container parameter matches for %some_config%.'); + $this->assertEquals($this->containerDefinition['parameters']['some_other_config'], $this->container->getParameter('some_other_config'), 'Container parameter matches for %some_other_config%.'); + } + + /** + * Tests that Container::getParameter() works properly for non-existing + * parameters. + * + * @covers ::getParameter + * @covers ::getParameterAlternatives + * @covers ::getAlternatives + * + * @expectedException \Symfony\Component\DependencyInjection\Exception\ParameterNotFoundException + */ + public function test_getParameter_notFound() { + $this->container->getParameter('parameter_that_does_not_exist'); + } + + /** + * Tests that Container::getParameter() works properly for NULL parameters. + * + * @covers ::getParameter + * + * @expectedException \Symfony\Component\DependencyInjection\Exception\ParameterNotFoundException + */ + public function test_getParameter_notFound_null() { + $this->container->getParameter(NULL); + } + + /** + * Tests that Container::hasParameter() works properly. + * @covers ::hasParameter */ - public function testSerialize() { - $container = new Container(); - serialize($container); + public function test_hasParameter() { + $this->assertTrue($this->container->hasParameter('some_config'), 'Container parameters include %some_config%.'); + $this->assertFalse($this->container->hasParameter('some_config_not_exists'), 'Container parameters do not include %some_config_not_exists%.'); } /** + * Tests that Container::setParameter() in an unfrozen case works properly. + * + * @covers ::setParameter + */ + public function test_setParameter_unfrozenContainer() { + $this->container = new $this->containerClass($this->containerDefinition, FALSE); + $this->container->setParameter('some_config', 'new_value'); + $this->assertEquals('new_value', $this->container->getParameter('some_config'), 'Container parameters can be set.'); + } + + /** + * Tests that Container::setParameter() in a frozen case works properly. + * + * @covers ::setParameter + * + * @expectedException LogicException + */ + public function test_setParameter_frozenContainer() { + $this->container = new $this->containerClass($this->containerDefinition, TRUE); + $this->container->setParameter('some_config', 'new_value'); + } + + /** + * Tests that Container::get() works properly. + * + * @covers ::get + * @covers ::createService + */ + public function test_get() { + $container = $this->container->get('service_container'); + $this->assertSame($this->container, $container, 'Container can be retrieved from itself.'); + + // Retrieve services of the container. + $other_service_class = $this->containerDefinition['services']['other.service']['class']; + $other_service = $this->container->get('other.service'); + $this->assertInstanceOf($other_service_class, $other_service, 'other.service has the right class.'); + + $some_parameter = $this->containerDefinition['parameters']['some_config']; + $some_other_parameter = $this->containerDefinition['parameters']['some_other_config']; + + $service = $this->container->get('service.provider'); + + $this->assertEquals($other_service, $service->getSomeOtherService(), '@other.service was injected via constructor.'); + $this->assertEquals($some_parameter, $service->getSomeParameter(), '%some_config% was injected via constructor.'); + $this->assertEquals($this->container, $service->getContainer(), 'Container was injected via setter injection.'); + $this->assertEquals($some_other_parameter, $service->getSomeOtherParameter(), '%some_other_config% was injected via setter injection.'); + $this->assertEquals($service->_someProperty, 'foo', 'Service has added properties.'); + } + + /** + * Tests that Container::get() for non-shared services works properly. + * + * @covers ::get + * @covers ::createService + */ + public function test_get_nonShared() { + $service = $this->container->get('non_shared_service'); + $service2 = $this->container->get('non_shared_service'); + + $this->assertNotSame($service, $service2, 'Non shared services are always re-instantiated.'); + } + + /** + * Tests that Container::get() works properly for class from parameters. + * @covers ::get + * @covers ::createService + */ + public function test_get_classFromParameter() { + $container = new $this->containerClass($this->containerDefinition, FALSE); + + $other_service_class = $this->containerDefinition['parameters']['some_parameter_class']; + $other_service = $container->get('other.service_class_from_parameter'); + $this->assertInstanceOf($other_service_class, $other_service, 'other.service_class_from_parameter has the right class.'); + } + + /** + * Tests that Container::set() works properly. + * + * @covers ::set + */ + public function test_set() { + $this->assertNull($this->container->get('new_id', ContainerInterface::NULL_ON_INVALID_REFERENCE)); + $mock_service = new MockService(); + $this->container->set('new_id', $mock_service); + + $this->assertSame($mock_service, $this->container->get('new_id'), 'A manual set service works as expected.'); + } + + /** + * Tests that set services have the right _serviceId property. + * * @covers ::set */ - public function testSet() { - $container = new Container(); - $class = new BarClass(); + public function test_set_serviceId() { + $container = new $this->containerClass(); + $class = new MockService(); $container->set('bar', $class); // Ensure that _serviceId is set on the object. $this->assertEquals('bar', $class->_serviceId); } + /** + * Tests that Container::has() works properly. + * + * @covers ::has + */ + public function test_has() { + $this->assertTrue($this->container->has('other.service')); + $this->assertFalse($this->container->has('another.service')); + + // Set the service manually, ensure that its also respected. + $mock_service = new MockService(); + $this->container->set('another.service', $mock_service); + $this->assertTrue($this->container->has('another.service')); + } + + /** + * Tests that Container::get() for circular dependencies works properly. + * @expectedException \Symfony\Component\DependencyInjection\Exception\ServiceCircularReferenceException + * @covers ::get + * @covers ::createService + */ + public function test_get_circular() { + $this->container->get('circular_dependency'); + } + + /** + * Tests that Container::get() for non-existant dependencies works properly. + * + * @covers ::get + * @covers ::createService + * @covers ::getAlternatives + * @covers ::getServiceAlternatives + * + * @expectedException \Symfony\Component\DependencyInjection\Exception\ServiceNotFoundException + */ + public function test_get_exception() { + $this->container->get('service_not_exists'); + } + + /** + * Tests that Container::get() for serialized definition works properly. + * @covers ::get + * @covers ::createService + */ + public function test_get_serializedDefinition() { + $container_definition = $this->containerDefinition; + $container_definition['services']['other.service'] = serialize($container_definition['services']['other.service']); + $container = new $this->containerClass($container_definition); + + // Retrieve services of the container. + $other_service_class = $this->containerDefinition['services']['other.service']['class']; + $other_service = $container->get('other.service'); + $this->assertInstanceOf($other_service_class, $other_service, 'other.service has the right class.'); + + $service = $container->get('service.provider'); + $this->assertEquals($other_service, $service->getSomeOtherService(), '@other.service was injected via constructor.'); + } + + + /** + * Tests that Container::get() for non-existant parameters works properly. + * @covers ::get + * @covers ::createService + * @covers ::resolveServicesAndParameters + */ + public function test_get_notFound_parameter() { + $service = $this->container->get('service_parameter_not_exists', ContainerInterface::NULL_ON_INVALID_REFERENCE); + $this->assertNull($service, 'Service is NULL.'); + } + + /** + * Tests Container::get() with an exception due to missing parameter on the second call. + * + * @covers ::get + * @covers ::createService + * @covers ::resolveServicesAndParameters + * + * @expectedException \Symfony\Component\DependencyInjection\Exception\InvalidArgumentException + */ + public function test_get_notFound_parameterWithExceptionOnSecondCall() { + $service = $this->container->get('service_parameter_not_exists', ContainerInterface::NULL_ON_INVALID_REFERENCE); + $this->assertNull($service, 'Service is NULL.'); + + // Reset the service. + $this->container->set('service_parameter_not_exists', NULL); + $this->container->get('service_parameter_not_exists'); + } + + /** + * Tests that Container::get() for non-existant parameters works properly. + * @expectedException \Symfony\Component\DependencyInjection\Exception\InvalidArgumentException + * @covers ::get + * @covers ::createService + * @covers ::resolveServicesAndParameters + */ + public function test_get_notFound_parameter_exception() { + $this->container->get('service_parameter_not_exists'); + } + + /** + * Tests that Container::get() for non-existent dependencies works properly. + * @covers ::get + * @covers ::createService + * @covers ::resolveServicesAndParameters + */ + public function test_get_notFound_dependency() { + $service = $this->container->get('service_dependency_not_exists', ContainerInterface::NULL_ON_INVALID_REFERENCE); + $this->assertNull($service, 'Service is NULL.'); + } + + /** + * Tests that Container::get() for non-existant dependencies works properly. + * @expectedException \Symfony\Component\DependencyInjection\Exception\ServiceNotFoundException + * @covers ::get + * @covers ::createService + * @covers ::resolveServicesAndParameters + * @covers ::getAlternatives + */ + public function test_get_notFound_dependency_exception() { + $this->container->get('service_dependency_not_exists'); + } + + + /** + * Tests that Container::get() for non-existant dependencies works properly. + * @covers ::get + * @covers ::createService + */ + public function test_get_notFound() { + $this->assertNull($this->container->get('service_not_exists', ContainerInterface::NULL_ON_INVALID_REFERENCE), 'Not found service does not throw exception.'); + } + + /** + * Tests that Container::get() for NULL service works properly. + * @covers ::get + * @covers ::createService + * + * @expectedException \Symfony\Component\DependencyInjection\Exception\ServiceNotFoundException + */ + public function test_get_notFound_NULL() { + $this->container->get(NULL); + } + + + /** + * Tests multiple Container::get() calls for non-existing dependencies work. + * + * @covers ::get + * @covers ::createService + */ + public function test_get_notFoundMultiple() { + $container = new $this->containerClass(); + + $this->assertNull($container->get('service_not_exists', ContainerInterface::NULL_ON_INVALID_REFERENCE, 'Not found service does not throw exception.')); + $this->assertNull($container->get('service_not_exists', ContainerInterface::NULL_ON_INVALID_REFERENCE, 'Not found service does not throw exception on second call.')); + } + + /** + * Tests multiple Container::get() calls with exception on the second time. + * + * @covers ::get + * @covers ::createService + * @covers ::getAlternatives + * + * @expectedException \Symfony\Component\DependencyInjection\Exception\ServiceNotFoundException + */ + public function test_get_notFoundMulitpleWithExceptionOnSecondCall() { + $this->assertNull($this->container->get('service_not_exists', ContainerInterface::NULL_ON_INVALID_REFERENCE, 'Not found service does nto throw exception.')); + $this->container->get('service_not_exists'); + } + + /** + * Tests that Container::get() for aliased services works properly. + * @covers ::get + * @covers ::createService + */ + public function test_get_alias() { + $service = $this->container->get('service.provider'); + $aliased_service = $this->container->get('service.provider_alias'); + $this->assertSame($service, $aliased_service); + } + + /** + * Tests that Container::get() for synthetic services works - if defined. + * + * @covers ::get + * @covers ::createService + */ + public function test_get_synthetic() { + $synthetic_service = new \stdClass(); + $this->container->set('synthetic', $synthetic_service); + $test_service = $this->container->get('synthetic'); + $this->assertSame($synthetic_service, $test_service); + } + + /** + * Tests that Container::get() for synthetic services throws an Exception if not defined. + * + * @covers ::get + * @covers ::createService + * + * @expectedException \Symfony\Component\DependencyInjection\Exception\RuntimeException + */ + public function test_get_synthetic_exception() { + $this->container->get('synthetic'); + } + + /** + * Tests that Container::get() for services with file includes works. + * + * @covers ::get + * @covers ::createService + */ + public function test_get_file() { + $file_service = $this->container->get('container_test_file_service_test'); + $this->assertTrue(function_exists('container_test_file_service_test_service_function')); + $this->assertEquals('Hello Container', container_test_file_service_test_service_function()); + } + + /** + * Tests that Container::get() for services with file includes works. + * + * @covers ::get + * @covers ::createService + * @covers ::resolveServicesAndParameters + */ + public function test_get_instantiation() { + $args = array(); + for ($i=0; $i < 12; $i++) { + $instantiation_service = $this->container->get('service_test_instantiation_'. $i); + $this->assertEquals($args, $instantiation_service->getArguments()); + $args[] = 'arg_' . $i; + } + } + + /** + * Tests that Container::get() for wrong factories works correctly. + * + * @covers ::get + * @covers ::createService + * + * @expectedException \Symfony\Component\DependencyInjection\Exception\RuntimeException + */ + public function test_get_factoryWrong() { + $this->container->get('wrong_factory'); + } + + /** + * Tests Container::get() for factories via services (Symfony 2.7.0). + * @covers ::get + * @covers ::createService + */ + public function test_get_factoryService() { + $factory_service = $this->container->get('factory_service'); + $factory_service_class = $this->container->getParameter('factory_service_class'); + $this->assertInstanceOf($factory_service_class, $factory_service); + } + + /** + * Tests that Container::get() for factories via class works (Symfony 2.7.0). + * @covers ::get + * @covers ::createService + */ + public function test_get_factoryClass() { + $service = $this->container->get('service.provider'); + $factory_service= $this->container->get('factory_class'); + + $this->assertInstanceOf(get_class($service), $factory_service); + $this->assertEquals('bar', $factory_service->getSomeParameter(), 'Correct parameter was passed via the factory class instantiation.'); + $this->assertEquals($this->container, $factory_service->getContainer(), 'Container was injected via setter injection.'); + } + + /** + * Tests that Container::get() for configurable services throws an Exception. + * + * @covers ::get + * @covers ::createService + * + * @expectedException \Symfony\Component\DependencyInjection\Exception\InvalidArgumentException + */ + public function test_get_configurator_exception() { + $this->container->get('configurable_service_exception'); + } + + /** + * Tests that Container::get() for configurable services works. + * @covers ::get + * @covers ::createService + */ + public function test_get_configurator() { + $container = $this->container; + + // Setup a configurator. + $configurator = $this->prophesize('\Drupal\Tests\Core\DependencyInjection\MockConfiguratorInterface'); + $configurator->configureService(Argument::type('object')) + ->shouldBeCalled(1) + ->will(function($args) use ($container) { + $args[0]->setContainer($container); + }); + $container->set('configurator', $configurator->reveal()); + + // Test that the configurator worked. + $service = $container->get('configurable_service'); + $this->assertSame($container, $service->getContainer(), 'Container was injected via configurator.'); + } + + /** + * Tests that private services work correctly. + * @covers ::get + * @covers ::createService + * @covers ::resolveServicesAndParameters + */ + public function test_resolveServicesAndParameters_privateService() { + $service = $this->container->get('service_using_private'); + $private_service = $service->getSomeOtherService(); + $this->assertEquals($private_service->getSomeParameter(), 'really_private_lama', 'Private was found successfully.'); + + // Test that sharing the same private services works. + $service = $this->container->get('another_service_using_private'); + $another_private_service = $service->getSomeOtherService(); + $this->assertNotSame($private_service, $another_private_service, 'Private service is not shared.'); + $this->assertEquals($private_service->getSomeParameter(), 'really_private_lama', 'Private was found successfully.'); + } + + /** + * Tests that private service sharing works correctly. + * + * @covers ::get + * @covers ::createService + * @covers ::resolveServicesAndParameters + */ + public function test_resolveServicesAndParameters_privateServiceShared() { + $service = $this->container->get('service_using_shared_private'); + $private_service = $service->getSomeOtherService(); + $this->assertEquals($private_service->getSomeParameter(), 'really_private_lama', 'Private was found successfully.'); + + // Test that sharing the same private services works. + $service = $this->container->get('another_service_using_shared_private'); + $same_private_service = $service->getSomeOtherService(); + $this->assertSame($private_service, $same_private_service, 'Private service is shared.'); + $this->assertEquals($private_service->getSomeParameter(), 'really_private_lama', 'Private was found successfully.'); + } + + /** + * Tests that services with an array of arguments work correctly. + * @covers ::get + * @covers ::createService + * @covers ::resolveServicesAndParameters + */ + public function test_resolveServicesAndParameters_array() { + $service = $this->container->get('service_using_array'); + $other_service = $this->container->get('other.service'); + $this->assertEquals($other_service, $service->getSomeOtherService(), '@other.service was injected via constructor.'); + } + + /** + * Tests that services that are optional work correctly. + * @covers ::get + * @covers ::createService + * @covers ::resolveServicesAndParameters + */ + public function test_resolveServicesAndParameters_optional() { + $service = $this->container->get('service_with_optional_dependency'); + $this->assertNull($service->getSomeOtherService(), 'other service was NULL was expected.'); + } + + /** + * Tests that an invalid argument throw an Exception. + * + * @covers ::get + * @covers ::createService + * @covers ::resolveServicesAndParameters + * + * @expectedException \Symfony\Component\DependencyInjection\Exception\InvalidArgumentException + */ + public function test_resolveServicesAndParameters_invalidArgument() { + $this->container->get('invalid_argument_service'); + } + + /** + * Tests that invalid arguments throw an Exception. + * + * @covers ::get + * @covers ::createService + * @covers ::resolveServicesAndParameters + * + * @expectedException \Symfony\Component\DependencyInjection\Exception\InvalidArgumentException + */ + public function test_resolveServicesAndParameters_invalidArguments() { + // In case the machine format is not used, we need to simulate the test failure. + if (!$this->machineFormat) { + throw new \Symfony\Component\DependencyInjection\Exception\InvalidArgumentException('Simulating the test failure.'); + } + $this->container->get('invalid_arguments_service'); + } + + /** + * Tests that a parameter that points to a service works correctly. + * + * @covers ::get + * @covers ::createService + * @covers ::resolveServicesAndParameters + */ + public function test_resolveServicesAndParameters_fromParameter() { + $service = $this->container->get('service.provider'); + $test_service = $this->container->get('service_with_parameter_service'); + $this->assertSame($service, $test_service->getSomeOtherService(), 'Service was passed via parameter.'); + } + + + /** + * Tests that Container::initialized works correctly. + * @covers ::initialized + */ + public function test_initialized() { + $this->assertFalse($this->container->initialized('late.service'), 'Late service is not initialized.'); + $this->container->get('late.service'); + $this->assertTrue($this->container->initialized('late.service'), 'Late service is initialized after it was retrieved once.'); + } + + /** + * Tests that Container::initialized works correctly for aliases. + * @covers ::initialized + */ + public function test_initialized_aliases() { + $this->assertFalse($this->container->initialized('late.service_alias'), 'Late service is not initialized.'); + $this->container->get('late.service'); + $this->assertTrue($this->container->initialized('late.service_alias'), 'Late service is initialized after it was retrieved once.'); + } + + /** + * Tests that unsupported methods throw an Exception. + * + * @covers ::enterScope + * @covers ::leaveScope + * @covers ::addScope + * @covers ::hasScope + * @covers ::isScopeActive + * + * @expectedException \BadMethodCallException + * + * @dataProvider scopeExceptionTestProvider + */ + public function test_scope_exception($method, $argument) { + $callable = array( + $this->container, + $method, + ); + + $callable($argument); + } + + /** + * Data provider for test_scope_exception(). + * + * @return array[] + * Returns per data set an array with: + * - method name to call + * - argument to pass + */ + public function scopeExceptionTestProvider() { + $scope = $this->prophesize('\Symfony\Component\DependencyInjection\ScopeInterface')->reveal(); + return array( + array('enterScope', 'test_scope'), + array('leaveScope', 'test_scope'), + array('hasScope', 'test_scope'), + array('isScopeActive', 'test_scope'), + array('addScope', $scope), + ); + } + + /** + * Tests that __sleep throws an Exception. + * + * @covers ::__sleep + * + * @expectedException \PHPUnit_Framework_Error + */ + public function test_sleep() { + $serialized = serialize($this->container); + } + + /** + * Tests that __sleep works when error handler is set to non-fatal. + * + * @covers ::__sleep + */ + public function test_sleep_working() { + $container = new $this->containerClass(); + + // Ignore any errors. + set_error_handler(array($this, 'ignoreErrorHandler')); + $serialized = serialize($container); + restore_error_handler(); + } + + /** + * An error handler that ignores all errors. + */ + public function ignoreErrorHandler() { + } + + + /** + * Returns a mock container definition. + * + * @return array + * Associated array with parameters and services. + */ + protected function getMockContainerDefinition() { + $fake_service = new \stdClass(); + $parameters = array(); + $parameters['some_parameter_class'] = get_class($fake_service); + $parameters['some_private_config'] = 'really_private_lama'; + $parameters['some_config'] = 'foo'; + $parameters['some_other_config'] = 'lama'; + $parameters['factory_service_class'] = get_class($fake_service); + // Also test alias resolving. + $parameters['service_from_parameter'] = $this->getServiceCall('service.provider_alias'); + + $services = array(); + $services['service_container'] = array( + 'class' => '\Drupal\service_container\DependencyInjection\Container', + ); + $services['other.service'] = array( + 'class' => get_class($fake_service), + ); + + $services['non_shared_service'] = array( + 'class' => get_class($fake_service), + 'shared' => FALSE, + ); + + $services['other.service_class_from_parameter'] = array( + 'class' => $this->getParameterCall('some_parameter_class'), + ); + $services['late.service'] = array( + 'class' => get_class($fake_service), + ); + $services['service.provider'] = array( + 'class' => '\Drupal\Tests\Core\DependencyInjection\MockService', + 'arguments' => $this->getCollection(array( + $this->getServiceCall('other.service'), + $this->getParameterCall('some_config'), + )), + 'properties' => $this->getCollection(array('_someProperty' => 'foo')), + 'calls' => array( + array('setContainer', $this->getCollection(array( + $this->getServiceCall('service_container'), + ))), + array('setOtherConfigParameter', $this->getCollection(array( + $this->getParameterCall('some_other_config'), + ))), + ), + 'priority' => 0, + ); + + // Test private services. + + $private_service = array( + 'class' => '\Drupal\Tests\Core\DependencyInjection\MockService', + 'arguments' => $this->getCollection(array( + $this->getServiceCall('other.service'), + $this->getParameterCall('some_private_config'), + )), + 'public' => FALSE, + ); + + $services['service_using_private'] = array( + 'class' => '\Drupal\Tests\Core\DependencyInjection\MockService', + 'arguments' => $this->getCollection(array( + $this->getPrivateServiceCall(NULL, $private_service), + $this->getParameterCall('some_config'), + )), + ); + $services['another_service_using_private'] = array( + 'class' => '\Drupal\Tests\Core\DependencyInjection\MockService', + 'arguments' => $this->getCollection(array( + $this->getPrivateServiceCall(NULL, $private_service), + $this->getParameterCall('some_config'), + )), + ); + + // Test shared private services. + + $id = 'private_service_shared_1'; + + $services['service_using_shared_private'] = array( + 'class' => '\Drupal\Tests\Core\DependencyInjection\MockService', + 'arguments' => $this->getCollection(array( + $this->getPrivateServiceCall($id, $private_service, TRUE), + $this->getParameterCall('some_config'), + )), + ); + $services['another_service_using_shared_private'] = array( + 'class' => '\Drupal\Tests\Core\DependencyInjection\MockService', + 'arguments' => $this->getCollection(array( + $this->getPrivateServiceCall($id, $private_service, TRUE), + $this->getParameterCall('some_config'), + )), + ); + + // Tests service with invalid argument. + $services['invalid_argument_service'] = array( + 'class' => '\Drupal\Tests\Core\DependencyInjection\MockService', + 'arguments' => $this->getCollection(array( + 1, // Test passing non-strings, too. + (object) array( + 'type' => 'invalid', + ), + )), + ); + + $services['invalid_arguments_service'] = array( + 'class' => '\Drupal\Tests\Core\DependencyInjection\MockService', + 'arguments' => (object) array( + 'type' => 'invalid', + ), + ); + + // Test service that needs deep-traversal. + $services['service_using_array'] = array( + 'class' => '\Drupal\Tests\Core\DependencyInjection\MockService', + 'arguments' => $this->getCollection(array( + $this->getCollection(array( + $this->getServiceCall('other.service'), + )), + $this->getParameterCall('some_private_config'), + )), + ); + + $services['service_with_optional_dependency'] = array( + 'class' => '\Drupal\Tests\Core\DependencyInjection\MockService', + 'arguments' => $this->getCollection(array( + $this->getServiceCall('service.does_not_exist', ContainerInterface::NULL_ON_INVALID_REFERENCE), + $this->getParameterCall('some_private_config'), + )), + + ); + + $services['factory_service'] = array( + 'class' => '\Drupal\service_container\ServiceContainer\ControllerInterface', + 'factory' => array( + $this->getServiceCall('service.provider'), + 'getFactoryMethod', + ), + 'arguments' => $this->getCollection(array( + $this->getParameterCall('factory_service_class'), + )), + ); + $services['factory_class'] = array( + 'class' => '\Drupal\service_container\ServiceContainer\ControllerInterface', + 'factory' => '\Drupal\Tests\Core\DependencyInjection\MockService::getFactoryMethod', + 'arguments' => array( + '\Drupal\Tests\Core\DependencyInjection\MockService', + array(NULL, 'bar'), + ), + 'calls' => array( + array('setContainer', $this->getCollection(array( + $this->getServiceCall('service_container'), + ))), + ), + ); + + $services['wrong_factory'] = array( + 'class' => '\Drupal\service_container\ServiceContainer\ControllerInterface', + 'factory' => (object) array('I am not a factory, but I pretend to be.'), + ); + + $services['circular_dependency'] = array( + 'class' => '\Drupal\Tests\Core\DependencyInjection\MockService', + 'arguments' => $this->getCollection(array( + $this->getServiceCall('circular_dependency'), + )), + ); + $services['synthetic'] = array( + 'synthetic' => TRUE, + ); + $services['container_test_file_service_test'] = array( + 'class' => '\stdClass', + 'file' => __DIR__ . '/Fixture/container_test_file_service_test_service_function.data', + ); + + // Test multiple arguments. + $args = array(); + for ($i=0; $i < 12; $i++) { + $services['service_test_instantiation_' . $i] = array( + 'class' => '\Drupal\Tests\Core\DependencyInjection\MockInstantiationService', + // Also test a collection that does not need resolving. + 'arguments' => $this->getCollection($args, FALSE), + ); + $args[] = 'arg_' . $i; + } + + $services['service_parameter_not_exists'] = array( + 'class' => '\Drupal\Tests\Core\DependencyInjection\MockService', + 'arguments' => $this->getCollection(array( + $this->getServiceCall('service.provider'), + $this->getParameterCall('not_exists'), + )), + ); + $services['service_dependency_not_exists'] = array( + 'class' => '\Drupal\Tests\Core\DependencyInjection\MockService', + 'arguments' => $this->getCollection(array( + $this->getServiceCall('service_not_exists'), + $this->getParameterCall('some_config'), + )), + ); + + $services['service_with_parameter_service'] = array( + 'class' => '\Drupal\Tests\Core\DependencyInjection\MockService', + 'arguments' => $this->getCollection(array( + $this->getParameterCall('service_from_parameter'), + // Also test deep collections that don't need resolving. + $this->getCollection(array( + 1, + ), FALSE), + )), + ); + + // To ensure getAlternatives() finds something. + $services['service_not_exists_similar'] = array( + 'synthetic' => TRUE, + ); + + // Test configurator. + $services['configurator'] = array( + 'synthetic' => TRUE, + ); + $services['configurable_service'] = array( + 'class' => '\Drupal\Tests\Core\DependencyInjection\MockService', + 'arguments' => array(), + 'configurator' => array( + $this->getServiceCall('configurator'), + 'configureService' + ), + ); + $services['configurable_service_exception'] = array( + 'class' => '\Drupal\Tests\Core\DependencyInjection\MockService', + 'arguments' => array(), + 'configurator' => 'configurator_service_test_does_not_exist', + ); + + $aliases = array(); + $aliases['service.provider_alias'] = 'service.provider'; + $aliases['late.service_alias'] = 'late.service'; + + return array( + 'aliases' => $aliases, + 'parameters' => $parameters, + 'services' => $services, + 'machine_format' => $this->machineFormat, + ); + } + + /** + * Helper function to return a service definition. + */ + protected function getServiceCall($id, $invalid_behavior = ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE) { + return (object) array( + 'type' => 'service', + 'id' => $id, + 'invalidBehavior' => $invalid_behavior, + ); + } + + /** + * Helper function to return a service definition. + */ + protected function getParameterCall($name) { + return (object) array( + 'type' => 'parameter', + 'name' => $name, + ); + } + + /** + * Helper function to return a private service definition. + */ + protected function getPrivateServiceCall($id, $service_definition, $shared = FALSE) { + if (!$id) { + $hash = sha1(serialize($service_definition)); + $id = 'private__' . $hash; + } + return (object) array( + 'type' => 'private_service', + 'id' => $id, + 'value' => $service_definition, + 'shared' => $shared, + ); + } + + /** + * Helper function to return a machine readable collection. + */ + protected function getCollection($collection, $resolve = TRUE) { + return (object) array( + 'type' => 'collection', + 'value' => $collection, + 'resolve' => $resolve, + ); + } + +} + +/** + * Helper interface to test Container::get() with configurator. + * + * @group DependencyInjection + */ +interface MockConfiguratorInterface { + + /** + * Configures a service. + * + * @param object $service + * The service to configure. + */ + public function configureService($service); + +} + + +/** + * Helper class to test Container::get() method for varying number of parameters. + * + * @group DependencyInjection + */ +class MockInstantiationService { + + /** + * @var mixed[] + */ + protected $arguments; + + /** + * Construct a mock instantiation service. + */ + public function __construct() { + $this->arguments = func_get_args(); + } + + /** + * Return arguments injected into the service. + * + * @return mixed[] + * Return the passed arguments. + */ + public function getArguments() { + return $this->arguments; + } + +} + + +/** + * Helper class to test Container::get() method. + * + * @group DependencyInjection + */ +class MockService { + + /** + * @var ContainerInterface + */ + protected $container; + + /** + * @var object + */ + protected $someOtherService; + + /** + * @var string + */ + protected $someParameter; + + /** + * @var string + */ + protected $someOtherParameter; + + /** + * Constructs a MockService object. + * + * @param object $some_other_service + * (optional) Another injected service. + * @param string $some_parameter + * (optional) An injected parameter. + */ + public function __construct($some_other_service = NULL, $some_parameter = NULL) { + if (is_array($some_other_service)) { + $some_other_service = $some_other_service[0]; + } + $this->someOtherService = $some_other_service; + $this->someParameter = $some_parameter; + } + + /** + * Sets the container object. + * + * @param ContainerInterface $container + * The container to inject via setter injection. + */ + public function setContainer(ContainerInterface $container) { + $this->container = $container; + } + + /** + * Gets the container object. + * + * @return ContainerInterface + * The internally set container. + */ + public function getContainer() { + return $this->container; + } + + /** + * Gets the someOtherService object. + * + * @return object + * The injected service. + */ + public function getSomeOtherService() { + return $this->someOtherService; + } + + /** + * Gets the someParameter property. + * + * @return string + * The injected parameter. + */ + public function getSomeParameter() { + return $this->someParameter; + } + + /** + * Sets the someOtherParameter property. + * + * @param string $some_other_parameter + * The setter injected parameter. + */ + public function setOtherConfigParameter($some_other_parameter) { + $this->someOtherParameter = $some_other_parameter; + } + + /** + * Gets the someOtherParameter property. + * + * @return string + * The injected parameter. + */ + public function getSomeOtherParameter() { + return $this->someOtherParameter; + } + + /** + * Provides a factory method to get a service. + * + * @param string $class + * The class name of the class to instantiate + * @param array $arguments + * (optional) Arguments to pass to the new class. + * + * @return object + * The instantiated service object. + */ + public static function getFactoryMethod($class, $arguments = array()) { + $r = new \ReflectionClass($class); + $service = ($r->getConstructor() === NULL) ? $r->newInstance() : $r->newInstanceArgs($arguments); + + return $service; + } + } diff --git a/core/tests/Drupal/Tests/Core/DependencyInjection/Dumper/DebugPhpArrayDumperTest.php b/core/tests/Drupal/Tests/Core/DependencyInjection/Dumper/DebugPhpArrayDumperTest.php deleted file mode 100644 index 91e9491..0000000 --- a/core/tests/Drupal/Tests/Core/DependencyInjection/Dumper/DebugPhpArrayDumperTest.php +++ /dev/null @@ -1,52 +0,0 @@ -machineFormat = FALSE; - $this->dumperClass = '\Drupal\Core\DependencyInjection\Dumper\DebugPhpArrayDumper'; - parent::setUp(); - } - - /** - * Helper function to return a service definition. - */ - protected function getServiceCall($id, $invalid_behavior = ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE) { - if ($invalid_behavior !== ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE) { - return sprintf('@?%s', $id); - } - - return sprintf('@%s', $id); - } - - /** - * Helper function to return a service definition. - */ - protected function getParameterCall($name) { - return '%' . $name . '%'; - } - - /** - * Helper function to return a machine readable '@notation'. - */ - protected function getCollection($collection, $resolve = TRUE) { - return $collection; - } - -} diff --git a/core/tests/Drupal/Tests/Core/DependencyInjection/Dumper/OptimizedPhpArrayDumperTest.php b/core/tests/Drupal/Tests/Core/DependencyInjection/Dumper/OptimizedPhpArrayDumperTest.php new file mode 100644 index 0000000..2de9b73 --- /dev/null +++ b/core/tests/Drupal/Tests/Core/DependencyInjection/Dumper/OptimizedPhpArrayDumperTest.php @@ -0,0 +1,587 @@ +containerBuilder = $this->prophesize('\Symfony\Component\DependencyInjection\ContainerBuilder'); + $this->containerBuilder->getAliases()->willReturn(array()); + $this->containerBuilder->getParameterBag()->willReturn(new ParameterBag()); + $this->containerBuilder->getDefinitions()->willReturn(NULL); + + $definition = array(); + $definition['aliases'] = array(); + $definition['parameters'] = array(); + $definition['services'] = array(); + $definition['machine_format'] = $this->machineFormat; + + $this->containerDefinition = $definition; + + // Create the dumper. + $this->dumper = new $this->dumperClass($this->containerBuilder->reveal()); + } + + /** + * Tests that an empty container works properly. + * + * @covers ::dump + * @covers ::getArray + * @covers ::getMachineFormat + */ + public function test_dump() { + $serialized_definition = $this->dumper->dump(); + $this->assertEquals(serialize($this->containerDefinition), $serialized_definition); + } + + /** + * Tests that alias processing works properly. + * + * @covers ::getAliases + * + * @dataProvider getAliasesDataProvider + */ + public function test_getAliases($aliases, $definition_aliases) { + $this->containerDefinition['aliases'] = $definition_aliases; + $this->containerBuilder->getAliases()->willReturn($aliases); + $this->assertEquals($this->containerDefinition, $this->dumper->getArray(), 'Expected definition matches dump.'); + } + + /** + * Data provider for test_getAliases(). + * + * @return array[] + * Returns data-set elements with: + * - aliases as returned by ContainerBuilder. + * - aliases as expected in the container definition. + */ + public function getAliasesDataProvider() { + return array( + array(array(), array()), + array( + array('foo' => 'foo.alias'), + array('foo' => 'foo.alias'), + ), + array( + array('foo' => 'foo.alias', 'foo.alias' => 'foo.alias.alias'), + array('foo' => 'foo.alias.alias', 'foo.alias' => 'foo.alias.alias'), + ), + ); + } + + /** + * Tests that parameter processing works properly. + * + * @covers ::getParameters + * @covers ::prepareParameters + * @covers ::escape + * @covers ::dumpValue + * @covers ::getReferenceCall + * + * @dataProvider getParametersDataProvider + */ + public function test_getParameters($parameters, $definition_parameters, $is_frozen) { + $this->containerDefinition['parameters'] = $definition_parameters; + + $parameter_bag = new ParameterBag($parameters); + $this->containerBuilder->getParameterBag()->willReturn($parameter_bag); + $this->containerBuilder->isFrozen()->willReturn($is_frozen); + + if (isset($parameters['reference'])) { + $definition = new Definition('\stdClass'); + $this->containerBuilder->getDefinition('referenced_service')->willReturn($definition); + } + + $this->assertEquals($this->containerDefinition, $this->dumper->getArray(), 'Expected definition matches dump.'); + } + + /** + * Data provider for test_getParameters(). + * + * @return array[] + * Returns data-set elements with: + * - parameters as returned by ContainerBuilder. + * - parameters as expected in the container definition. + * - frozen value + */ + public function getParametersDataProvider() { + return array( + array(array(), array(), TRUE), + array( + array('foo' => 'value_foo'), + array('foo' => 'value_foo'), + TRUE, + ), + array( + array('foo' => array('llama' => 'yes')), + array('foo' => array('llama' => 'yes')), + TRUE, + ), + array( + array('foo' => '%llama%', 'llama' => 'yes'), + array('foo' => '%%llama%%', 'llama' => 'yes'), + TRUE, + ), + array( + array('foo' => '%llama%', 'llama' => 'yes'), + array('foo' => '%llama%', 'llama' => 'yes'), + FALSE, + ), + array( + array('reference' => new Reference('referenced_service')), + array('reference' => $this->getServiceCall('referenced_service')), + TRUE, + ), + ); + } + + /** + * Tests that service processing works properly. + * + * @covers ::getServiceDefinitions + * @covers ::getServiceDefinition + * @covers ::dumpMethodCalls + * @covers ::dumpCollection + * @covers ::dumpCallable + * @covers ::dumpValue + * @covers ::getPrivateServiceCall + * @covers ::getReferenceCall + * @covers ::getServiceCall + * @covers ::getParameterCall + * + * @dataProvider getDefinitionsDataProvider + */ + public function test_getServiceDefinitions($services, $definition_services) { + $this->containerDefinition['services'] = $definition_services; + + $this->containerBuilder->getDefinitions()->willReturn($services); + + $bar_definition = new Definition('\stdClass'); + $this->containerBuilder->getDefinition('bar')->willReturn($bar_definition); + + $private_definition = new Definition('\stdClass'); + $private_definition->setPublic(FALSE); + + $this->containerBuilder->getDefinition('private_definition')->willReturn($private_definition); + + $this->assertEquals($this->containerDefinition, $this->dumper->getArray(), 'Expected definition matches dump.'); + } + + /** + * Data provider for test_getServiceDefinitions(). + * + * @return array[] + * Returns data-set elements with: + * - parameters as returned by ContainerBuilder. + * - parameters as expected in the container definition. + * - frozen value + */ + public function getDefinitionsDataProvider() { + $base_service_definition = array( + 'class' => '\stdClass', + 'public' => TRUE, + 'file' => FALSE, + 'synthetic' => FALSE, + 'lazy' => FALSE, + 'arguments' => array(), + 'arguments_count' => 0, + 'properties' => array(), + 'calls' => array(), + 'scope' => ContainerInterface::SCOPE_CONTAINER, + 'shared' => TRUE, + 'factory' => FALSE, + 'configurator' => FALSE, + ); + + // Test basic flags. + $service_definitions[] = array( + ) + $base_service_definition; + + $service_definitions[] = array( + 'public' => FALSE, + ) + $base_service_definition; + + $service_definitions[] = array( + 'file' => 'test_include.php', + ) + $base_service_definition; + + $service_definitions[] = array( + 'synthetic' => TRUE, + ) + $base_service_definition; + + $service_definitions[] = array( + 'lazy' => TRUE, + ) + $base_service_definition; + + // Test a basic public Reference. + $service_definitions[] = array( + 'arguments' => array( 'foo', new Reference('bar')), + 'arguments_count' => 2, + 'arguments_expected' => $this->getCollection(array('foo', $this->getServiceCall('bar'))), + ) + $base_service_definition; + + // Test a public reference that should not throw an Exception. + $reference = new Reference('bar', ContainerInterface::NULL_ON_INVALID_REFERENCE); + $service_definitions[] = array( + 'arguments' => array($reference), + 'arguments_count' => 1, + 'arguments_expected' => $this->getCollection(array($this->getServiceCall('bar', ContainerInterface::NULL_ON_INVALID_REFERENCE))), + ) + $base_service_definition; + + + // Test a private shared servied, denoted by having a Reference. + $private_definition = array( + 'class' => '\stdClass', + 'public' => FALSE, + 'arguments_count' => 0, + ); + + $service_definitions[] = array( + 'arguments' => array( 'foo', new Reference('private_definition')), + 'arguments_count' => 2, + 'arguments_expected' => $this->getCollection(array('foo', $this->getPrivateServiceCall('private_definition', $private_definition, TRUE ))), + ) + $base_service_definition; + + // Test a private non-shared service, denoted by having a Definition. + $private_definition_object = new Definition('\stdClass'); + $private_definition_object->setPublic(FALSE); + + $service_definitions[] = array( + 'arguments' => array( 'foo', $private_definition_object), + 'arguments_count' => 2, + 'arguments_expected' => $this->getCollection(array('foo', $this->getPrivateServiceCall(NULL, $private_definition))), + ) + $base_service_definition; + + // Test a deep collection without a reference. + $service_definitions[] = array( + 'arguments' => array(array(array('foo'))), + 'arguments_count' => 1, + ) + $base_service_definition; + + // Test a deep collection with a reference to resolve. + $service_definitions[] = array( + 'arguments' => array(array(new Reference('bar'))), + 'arguments_count' => 1, + 'arguments_expected' => $this->getCollection(array($this->getCollection(array($this->getServiceCall('bar'))))), + ) + $base_service_definition; + + // Test a collection with a variable to resolve. + $service_definitions[] = array( + 'arguments' => array(new Parameter('llama_parameter')), + 'arguments_count' => 1, + 'arguments_expected' => $this->getCollection(array($this->getParameterCall('llama_parameter'))), + ) + $base_service_definition; + + // Test objects that have _serviceId property. + $drupal_service = new \stdClass(); + $drupal_service->_serviceId = 'bar'; + + $service_definitions[] = array( + 'arguments' => array($drupal_service), + 'arguments_count' => 1, + 'arguments_expected' => $this->getCollection(array($this->getServiceCall('bar'))), + ) + $base_service_definition; + + // Test getMethodCalls. + $calls = array( + array('method', $this->getCollection(array())), + array('method2', $this->getCollection(array())), + ); + $service_definitions[] = array( + 'calls' => $calls, + ) + $base_service_definition; + + $service_definitions[] = array( + 'scope' => ContainerInterface::SCOPE_PROTOTYPE, + 'shared' => FALSE, + ) + $base_service_definition; + + // Test factory. + $service_definitions[] = array( + 'factory' => array(new Reference('bar'), 'factoryMethod'), + 'factory_expected' => array($this->getServiceCall('bar'), 'factoryMethod'), + ) + $base_service_definition; + + // Test invalid factory - needed to test deep dumpValue(). + $service_definitions[] = array( + 'factory' => array(array('foo', 'llama'), 'factoryMethod'), + ) + $base_service_definition; + + // Test properties. + $service_definitions[] = array( + 'properties' => array( '_value' => 'llama' ), + ) + $base_service_definition; + + // Test configurator. + $service_definitions[] = array( + 'configurator' => array(new Reference('bar'), 'configureService'), + 'configurator_expected' => array($this->getServiceCall('bar'), 'configureService'), + ) + $base_service_definition; + + $services_provided = array(); + $services_provided[] = array( + array(), + array(), + ); + + foreach ($service_definitions as $service_definition) { + $definition = $this->prophesize('\Symfony\Component\DependencyInjection\Definition'); + $definition->getClass()->willReturn($service_definition['class']); + $definition->isPublic()->willReturn($service_definition['public']); + $definition->getFile()->willReturn($service_definition['file']); + $definition->isSynthetic()->willReturn($service_definition['synthetic']); + $definition->isLazy()->willReturn($service_definition['lazy']); + $definition->getArguments()->willReturn($service_definition['arguments']); + $definition->getProperties()->willReturn($service_definition['properties']); + $definition->getMethodCalls()->willReturn($service_definition['calls']); + $definition->getScope()->willReturn($service_definition['scope']); + $definition->getDecoratedService()->willReturn(NULL); + $definition->getFactory()->willReturn($service_definition['factory']); + $definition->getConfigurator()->willReturn($service_definition['configurator']); + + // Preserve order. + $filtered_service_definition = array(); + foreach ($base_service_definition as $key => $value) { + $filtered_service_definition[$key] = $service_definition[$key]; + unset($service_definition[$key]); + + if ($key == 'class' || $key == 'arguments_count') { + continue; + } + + if ($filtered_service_definition[$key] === $base_service_definition[$key]) { + unset($filtered_service_definition[$key]); + } + } + + // Add remaining properties. + $filtered_service_definition += $service_definition; + + // Allow to set _expected values. + foreach (array('arguments', 'factory', 'configurator') as $key) { + $expected = $key . '_expected'; + if (isset($filtered_service_definition[$expected])) { + $filtered_service_definition[$key] = $filtered_service_definition[$expected]; + unset($filtered_service_definition[$expected]); + } + } + + // Remove any remaining scope. + unset($filtered_service_definition['scope']); + + if (isset($filtered_service_definition['public']) && $filtered_service_definition['public'] === FALSE) { + $services_provided[] = array( + array('foo_service' => $definition->reveal()), + array(), + ); + continue; + } + + $services_provided[] = array( + array('foo_service' => $definition->reveal()), + array('foo_service' => $this->serializeDefinition($filtered_service_definition)), + ); + } + + return $services_provided; + } + + /** + * Helper function to serialize a definition. + * + * Used to override serialization. + */ + protected function serializeDefinition(array $service_definition) { + return serialize($service_definition); + } + + /** + * Helper function to return a service definition. + */ + protected function getServiceCall($id, $invalid_behavior = ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE) { + return (object) array( + 'type' => 'service', + 'id' => $id, + 'invalidBehavior' => $invalid_behavior, + ); + } + + /** + * Tests that the correct InvalidArgumentException is thrown for getScope(). + * + * @covers ::getServiceDefinition + * + * @expectedException \Symfony\Component\DependencyInjection\Exception\InvalidArgumentException + */ + public function test_getServiceDefinition_getScope() { + $bar_definition = new Definition('\stdClass'); + $bar_definition->setScope('foo_scope'); + $services['bar'] = $bar_definition; + + $this->containerBuilder->getDefinitions()->willReturn($services); + $this->dumper->getArray(); + } + + /** + * Tests that the correct InvalidArgumentException is thrown for getDecoratedService(). + * + * @covers ::getServiceDefinition + * + * @expectedException \Symfony\Component\DependencyInjection\Exception\InvalidArgumentException + */ + public function test_getServiceDefinition_getDecoratedService() { + $bar_definition = new Definition('\stdClass'); + $bar_definition->setDecoratedService(new Reference('foo')); + $services['bar'] = $bar_definition; + + $this->containerBuilder->getDefinitions()->willReturn($services); + $this->dumper->getArray(); + } + + /** + * Tests that the correct RuntimeException is thrown for expressions. + * + * @covers ::dumpValue + * @covers ::getExpressionCall + * + * @expectedException \Symfony\Component\DependencyInjection\Exception\RuntimeException + */ + public function test_getServiceDefinition_getExpressionCall() { + $expression = new Expression(); + + $bar_definition = new Definition('\stdClass'); + $bar_definition->addArgument($expression); + $services['bar'] = $bar_definition; + + $this->containerBuilder->getDefinitions()->willReturn($services); + $this->dumper->getArray(); + } + + /** + * Tests that the correct RuntimeException is thrown for dumping an object. + * + * @covers ::dumpValue + * + * @expectedException \Symfony\Component\DependencyInjection\Exception\RuntimeException + */ + public function test_getServiceDefinition_dumpObject() { + $service = new \stdClass(); + + $bar_definition = new Definition('\stdClass'); + $bar_definition->addArgument($service); + $services['bar'] = $bar_definition; + + $this->containerBuilder->getDefinitions()->willReturn($services); + $this->dumper->getArray(); + } + + /** + * Tests that the correct RuntimeException is thrown for dumping a resource. + * + * @covers ::dumpValue + * + * @expectedException \Symfony\Component\DependencyInjection\Exception\RuntimeException + */ + public function test_getServiceDefinition_dumpResource() { + $resource = fopen('php://memory', 'r'); + + $bar_definition = new Definition('\stdClass'); + $bar_definition->addArgument($resource); + $services['bar'] = $bar_definition; + + $this->containerBuilder->getDefinitions()->willReturn($services); + $this->dumper->getArray(); + } + + /** + * Helper function to return a private service definition. + */ + protected function getPrivateServiceCall($id, $service_definition, $shared = FALSE) { + if (!$id) { + $hash = sha1(serialize($service_definition)); + $id = 'private__' . $hash; + } + return (object) array( + 'type' => 'private_service', + 'id' => $id, + 'value' => $service_definition, + 'shared' => $shared, + ); + } + + /** + * Helper function to return a machine readable collection. + */ + protected function getCollection($collection, $resolve = TRUE) { + return (object) array( + 'type' => 'collection', + 'value' => $collection, + 'resolve' => $resolve, + ); + } + + /** + * Helper function to return a service definition. + */ + protected function getParameterCall($name) { + return (object) array( + 'type' => 'parameter', + 'name' => $name, + ); + } + +} + +} + +/* + * As Drupal Core does not ship with ExpressionLanguage component we need to + * define a dummy, else it cannot be tested. + */ +namespace Symfony\Component\ExpressionLanguage { + if (!class_exists('\Symfony\Component\ExpressionLanguage\Expression')) { + class Expression { + + /** + * Returns the expression as a String. + */ + public function __toString() { + return 'dummy_expression'; + } + } + } +} diff --git a/core/tests/Drupal/Tests/Core/DependencyInjection/Dumper/PhpArrayDumperTest.php b/core/tests/Drupal/Tests/Core/DependencyInjection/Dumper/PhpArrayDumperTest.php index 17456e6..b9dadb1 100644 --- a/core/tests/Drupal/Tests/Core/DependencyInjection/Dumper/PhpArrayDumperTest.php +++ b/core/tests/Drupal/Tests/Core/DependencyInjection/Dumper/PhpArrayDumperTest.php @@ -5,583 +5,48 @@ * Contains \Drupal\Tests\Core\DependencyInjection\Dumper\PhpArrayDumperTest. */ -namespace Drupal\Tests\Core\DependencyInjection\Dumper { +namespace Drupal\Tests\Core\DependencyInjection\Dumper; -use Symfony\Component\DependencyInjection\Definition; -use Symfony\Component\DependencyInjection\Reference; -use Symfony\Component\DependencyInjection\Parameter; -use Symfony\Component\ExpressionLanguage\Expression; -use Symfony\Component\DependencyInjection\ParameterBag\ParameterBag; use Symfony\Component\DependencyInjection\ContainerInterface; /** * @coversDefaultClass \Drupal\Core\DependencyInjection\Dumper\PhpArrayDumper - * @group container + * @group DependencyInjection */ -class PhpArrayDumperTest extends \PHPUnit_Framework_TestCase { - - /** - * Whether the dumper uses the machine format or not. - * - * @var bool - */ - protected $machineFormat = TRUE; - - /** - * Stores the dumper class to use. - * - * @var string - */ - protected $dumperClass = '\Drupal\Core\DependencyInjection\Dumper\PhpArrayDumper'; +class PhpArrayDumperTest extends OptimizedPhpArrayDumperTest { /** * {@inheritdoc} */ public function setUp() { - // Setup a mock container builder. - $this->containerBuilder = $this->prophesize('\Symfony\Component\DependencyInjection\ContainerBuilder'); - $this->containerBuilder->getAliases()->willReturn(array()); - $this->containerBuilder->getParameterBag()->willReturn(new ParameterBag()); - $this->containerBuilder->getDefinitions()->willReturn(NULL); - - $definition = array(); - $definition['aliases'] = array(); - $definition['parameters'] = array(); - $definition['services'] = array(); - $definition['machine_format'] = $this->machineFormat; - - $this->containerDefinition = $definition; - - // Create the dumper. - $this->dumper = new $this->dumperClass($this->containerBuilder->reveal()); - } - - /** - * Tests that an empty container works properly. - * - * @covers ::dump - * @covers ::getArray - * @covers ::getMachineFormat - */ - public function test_dump() { - $serialized_definition = $this->dumper->dump(); - $this->assertEquals(serialize($this->containerDefinition), $serialized_definition); - } - - /** - * Tests that alias processing works properly. - * - * @covers ::getAliases - * - * @dataProvider getAliasesDataProvider - */ - public function test_getAliases($aliases, $definition_aliases) { - $this->containerDefinition['aliases'] = $definition_aliases; - $this->containerBuilder->getAliases()->willReturn($aliases); - $this->assertEquals($this->containerDefinition, $this->dumper->getArray(), 'Expected definition matches dump.'); - } - - /** - * Data provider for test_getAliases(). - * - * @return array[] - * Returns data-set elements with: - * - aliases as returned by ContainerBuilder. - * - aliases as expected in the container definition. - */ - public function getAliasesDataProvider() { - return array( - array(array(), array()), - array( - array('foo' => 'foo.alias'), - array('foo' => 'foo.alias'), - ), - array( - array('foo' => 'foo.alias', 'foo.alias' => 'foo.alias.alias'), - array('foo' => 'foo.alias.alias', 'foo.alias' => 'foo.alias.alias'), - ), - ); - } - - /** - * Tests that parameter processing works properly. - * - * @covers ::getParameters - * @covers ::prepareParameters - * @covers ::escape - * @covers ::dumpValue - * @covers ::getReferenceCall - * - * @dataProvider getParametersDataProvider - */ - public function test_getParameters($parameters, $definition_parameters, $is_frozen) { - $this->containerDefinition['parameters'] = $definition_parameters; - - $parameter_bag = new ParameterBag($parameters); - $this->containerBuilder->getParameterBag()->willReturn($parameter_bag); - $this->containerBuilder->isFrozen()->willReturn($is_frozen); - - if (isset($parameters['reference'])) { - $definition = new Definition('\stdClass'); - $this->containerBuilder->getDefinition('referenced_service')->willReturn($definition); - } - - $this->assertEquals($this->containerDefinition, $this->dumper->getArray(), 'Expected definition matches dump.'); - } - - /** - * Data provider for test_getParameters(). - * - * @return array[] - * Returns data-set elements with: - * - parameters as returned by ContainerBuilder. - * - parameters as expected in the container definition. - * - frozen value - */ - public function getParametersDataProvider() { - return array( - array(array(), array(), TRUE), - array( - array('foo' => 'value_foo'), - array('foo' => 'value_foo'), - TRUE, - ), - array( - array('foo' => array('llama' => 'yes')), - array('foo' => array('llama' => 'yes')), - TRUE, - ), - array( - array('foo' => '%llama%', 'llama' => 'yes'), - array('foo' => '%%llama%%', 'llama' => 'yes'), - TRUE, - ), - array( - array('foo' => '%llama%', 'llama' => 'yes'), - array('foo' => '%llama%', 'llama' => 'yes'), - FALSE, - ), - array( - array('reference' => new Reference('referenced_service')), - array('reference' => $this->getServiceCall('referenced_service')), - TRUE, - ), - ); - } - - /** - * Tests that service processing works properly. - * - * @covers ::getServiceDefinitions - * @covers ::getServiceDefinition - * @covers ::dumpMethodCalls - * @covers ::dumpCollection - * @covers ::dumpCallable - * @covers ::dumpValue - * @covers ::getPrivateServiceCall - * @covers ::getReferenceCall - * @covers ::getServiceCall - * @covers ::getParameterCall - * - * @dataProvider getDefinitionsDataProvider - */ - public function test_getServiceDefinitions($services, $definition_services) { - $this->containerDefinition['services'] = $definition_services; - - $this->containerBuilder->getDefinitions()->willReturn($services); - - $bar_definition = new Definition('\stdClass'); - $this->containerBuilder->getDefinition('bar')->willReturn($bar_definition); - - $private_definition = new Definition('\stdClass'); - $private_definition->setPublic(FALSE); - - $this->containerBuilder->getDefinition('private_definition')->willReturn($private_definition); - - $this->assertEquals($this->containerDefinition, $this->dumper->getArray(), 'Expected definition matches dump.'); - } - - /** - * Data provider for test_getServiceDefinitions(). - * - * @return array[] - * Returns data-set elements with: - * - parameters as returned by ContainerBuilder. - * - parameters as expected in the container definition. - * - frozen value - */ - public function getDefinitionsDataProvider() { - $base_service_definition = array( - 'class' => '\stdClass', - 'public' => TRUE, - 'file' => FALSE, - 'synthetic' => FALSE, - 'lazy' => FALSE, - 'arguments' => array(), - 'arguments_count' => 0, - 'properties' => array(), - 'calls' => array(), - 'scope' => ContainerInterface::SCOPE_CONTAINER, - 'shared' => TRUE, - 'factory' => FALSE, - 'configurator' => FALSE, - ); - - // Test basic flags. - $service_definitions[] = array( - ) + $base_service_definition; - - $service_definitions[] = array( - 'public' => FALSE, - ) + $base_service_definition; - - $service_definitions[] = array( - 'file' => 'test_include.php', - ) + $base_service_definition; - - $service_definitions[] = array( - 'synthetic' => TRUE, - ) + $base_service_definition; - - $service_definitions[] = array( - 'lazy' => TRUE, - ) + $base_service_definition; - - // Test a basic public Reference. - $service_definitions[] = array( - 'arguments' => array( 'foo', new Reference('bar')), - 'arguments_count' => 2, - 'arguments_expected' => $this->getCollection(array('foo', $this->getServiceCall('bar'))), - ) + $base_service_definition; - - // Test a public reference that should not throw an Exception. - $reference = new Reference('bar', ContainerInterface::NULL_ON_INVALID_REFERENCE); - $service_definitions[] = array( - 'arguments' => array($reference), - 'arguments_count' => 1, - 'arguments_expected' => $this->getCollection(array($this->getServiceCall('bar', ContainerInterface::NULL_ON_INVALID_REFERENCE))), - ) + $base_service_definition; - - - // Test a private shared servied, denoted by having a Reference. - $private_definition = array( - 'class' => '\stdClass', - 'public' => FALSE, - 'arguments_count' => 0, - ); - - $service_definitions[] = array( - 'arguments' => array( 'foo', new Reference('private_definition')), - 'arguments_count' => 2, - 'arguments_expected' => $this->getCollection(array('foo', $this->getPrivateServiceCall('private_definition', $private_definition, TRUE ))), - ) + $base_service_definition; - - // Test a private non-shared service, denoted by having a Definition. - $private_definition_object = new Definition('\stdClass'); - $private_definition_object->setPublic(FALSE); - - $service_definitions[] = array( - 'arguments' => array( 'foo', $private_definition_object), - 'arguments_count' => 2, - 'arguments_expected' => $this->getCollection(array('foo', $this->getPrivateServiceCall(NULL, $private_definition))), - ) + $base_service_definition; - - // Test a deep collection without a reference. - $service_definitions[] = array( - 'arguments' => array(array(array('foo'))), - 'arguments_count' => 1, - ) + $base_service_definition; - - // Test a deep collection with a reference to resolve. - $service_definitions[] = array( - 'arguments' => array(array(new Reference('bar'))), - 'arguments_count' => 1, - 'arguments_expected' => $this->getCollection(array($this->getCollection(array($this->getServiceCall('bar'))))), - ) + $base_service_definition; - - // Test a collection with a variable to resolve. - $service_definitions[] = array( - 'arguments' => array(new Parameter('llama_parameter')), - 'arguments_count' => 1, - 'arguments_expected' => $this->getCollection(array($this->getParameterCall('llama_parameter'))), - ) + $base_service_definition; - - // Test objects that have _serviceId property. - $drupal_service = new \stdClass(); - $drupal_service->_serviceId = 'bar'; - - $service_definitions[] = array( - 'arguments' => array($drupal_service), - 'arguments_count' => 1, - 'arguments_expected' => $this->getCollection(array($this->getServiceCall('bar'))), - ) + $base_service_definition; - - // Test getMethodCalls. - $calls = array( - array('method', $this->getCollection(array())), - array('method2', $this->getCollection(array())), - ); - $service_definitions[] = array( - 'calls' => $calls, - ) + $base_service_definition; - - $service_definitions[] = array( - 'scope' => ContainerInterface::SCOPE_PROTOTYPE, - 'shared' => FALSE, - ) + $base_service_definition; - - // Test factory. - $service_definitions[] = array( - 'factory' => array(new Reference('bar'), 'factoryMethod'), - 'factory_expected' => array($this->getServiceCall('bar'), 'factoryMethod'), - ) + $base_service_definition; - - // Test invalid factory - needed to test deep dumpValue(). - $service_definitions[] = array( - 'factory' => array(array('foo', 'llama'), 'factoryMethod'), - ) + $base_service_definition; - - // Test properties. - $service_definitions[] = array( - 'properties' => array( '_value' => 'llama' ), - ) + $base_service_definition; - - // Test configurator. - $service_definitions[] = array( - 'configurator' => array(new Reference('bar'), 'configureService'), - 'configurator_expected' => array($this->getServiceCall('bar'), 'configureService'), - ) + $base_service_definition; - - $services_provided = array(); - $services_provided[] = array( - array(), - array(), - ); - - foreach ($service_definitions as $service_definition) { - $definition = $this->prophesize('\Symfony\Component\DependencyInjection\Definition'); - $definition->getClass()->willReturn($service_definition['class']); - $definition->isPublic()->willReturn($service_definition['public']); - $definition->getFile()->willReturn($service_definition['file']); - $definition->isSynthetic()->willReturn($service_definition['synthetic']); - $definition->isLazy()->willReturn($service_definition['lazy']); - $definition->getArguments()->willReturn($service_definition['arguments']); - $definition->getProperties()->willReturn($service_definition['properties']); - $definition->getMethodCalls()->willReturn($service_definition['calls']); - $definition->getScope()->willReturn($service_definition['scope']); - $definition->getDecoratedService()->willReturn(NULL); - $definition->getFactory()->willReturn($service_definition['factory']); - $definition->getConfigurator()->willReturn($service_definition['configurator']); - - // Preserve order. - $filtered_service_definition = array(); - foreach ($base_service_definition as $key => $value) { - $filtered_service_definition[$key] = $service_definition[$key]; - unset($service_definition[$key]); - - if ($key == 'class' || $key == 'arguments_count') { - continue; - } - - if ($filtered_service_definition[$key] === $base_service_definition[$key]) { - unset($filtered_service_definition[$key]); - } - } - - // Add remaining properties. - $filtered_service_definition += $service_definition; - - // Allow to set _expected values. - foreach (array('arguments', 'factory', 'configurator') as $key) { - $expected = $key . '_expected'; - if (isset($filtered_service_definition[$expected])) { - $filtered_service_definition[$key] = $filtered_service_definition[$expected]; - unset($filtered_service_definition[$expected]); - } - } - - // Remove any remaining scope. - unset($filtered_service_definition['scope']); - - if (isset($filtered_service_definition['public']) && $filtered_service_definition['public'] === FALSE) { - $services_provided[] = array( - array('foo_service' => $definition->reveal()), - array(), - ); - continue; - } - - $services_provided[] = array( - array('foo_service' => $definition->reveal()), - array('foo_service' => $this->serializeDefinition($filtered_service_definition)), - ); - } - - return $services_provided; - } - - /** - * Helper function to serialize a definition. - * - * Used to override serialization. - */ - protected function serializeDefinition(array $service_definition) { - return serialize($service_definition); + $this->machineFormat = FALSE; + $this->dumperClass = '\Drupal\Core\DependencyInjection\Dumper\PhpArrayDumper'; + parent::setUp(); } /** * Helper function to return a service definition. */ protected function getServiceCall($id, $invalid_behavior = ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE) { - return (object) array( - 'type' => 'service', - 'id' => $id, - 'invalidBehavior' => $invalid_behavior, - ); - } - - /** - * Tests that the correct InvalidArgumentException is thrown for getScope(). - * - * @covers ::getServiceDefinition - * - * @expectedException \Symfony\Component\DependencyInjection\Exception\InvalidArgumentException - */ - public function test_getServiceDefinition_getScope() { - $bar_definition = new Definition('\stdClass'); - $bar_definition->setScope('foo_scope'); - $services['bar'] = $bar_definition; - - $this->containerBuilder->getDefinitions()->willReturn($services); - $this->dumper->getArray(); - } - - /** - * Tests that the correct InvalidArgumentException is thrown for getDecoratedService(). - * - * @covers ::getServiceDefinition - * - * @expectedException \Symfony\Component\DependencyInjection\Exception\InvalidArgumentException - */ - public function test_getServiceDefinition_getDecoratedService() { - $bar_definition = new Definition('\stdClass'); - $bar_definition->setDecoratedService(new Reference('foo')); - $services['bar'] = $bar_definition; - - $this->containerBuilder->getDefinitions()->willReturn($services); - $this->dumper->getArray(); - } - - /** - * Tests that the correct RuntimeException is thrown for expressions. - * - * @covers ::dumpValue - * @covers ::getExpressionCall - * - * @expectedException \Symfony\Component\DependencyInjection\Exception\RuntimeException - */ - public function test_getServiceDefinition_getExpressionCall() { - $expression = new Expression(); - - $bar_definition = new Definition('\stdClass'); - $bar_definition->addArgument($expression); - $services['bar'] = $bar_definition; - - $this->containerBuilder->getDefinitions()->willReturn($services); - $this->dumper->getArray(); - } - - /** - * Tests that the correct RuntimeException is thrown for dumping an object. - * - * @covers ::dumpValue - * - * @expectedException \Symfony\Component\DependencyInjection\Exception\RuntimeException - */ - public function test_getServiceDefinition_dumpObject() { - $service = new \stdClass(); - - $bar_definition = new Definition('\stdClass'); - $bar_definition->addArgument($service); - $services['bar'] = $bar_definition; - - $this->containerBuilder->getDefinitions()->willReturn($services); - $this->dumper->getArray(); - } - - /** - * Tests that the correct RuntimeException is thrown for dumping a resource. - * - * @covers ::dumpValue - * - * @expectedException \Symfony\Component\DependencyInjection\Exception\RuntimeException - */ - public function test_getServiceDefinition_dumpResource() { - $resource = fopen('php://memory', 'r'); - - $bar_definition = new Definition('\stdClass'); - $bar_definition->addArgument($resource); - $services['bar'] = $bar_definition; + if ($invalid_behavior !== ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE) { + return sprintf('@?%s', $id); + } - $this->containerBuilder->getDefinitions()->willReturn($services); - $this->dumper->getArray(); + return sprintf('@%s', $id); } /** - * Helper function to return a private service definition. + * Helper function to return a service definition. */ - protected function getPrivateServiceCall($id, $service_definition, $shared = FALSE) { - if (!$id) { - $hash = sha1(serialize($service_definition)); - $id = 'private__' . $hash; - } - return (object) array( - 'type' => 'private_service', - 'id' => $id, - 'value' => $service_definition, - 'shared' => $shared, - ); + protected function getParameterCall($name) { + return '%' . $name . '%'; } /** - * Helper function to return a machine readable collection. + * Helper function to return a machine readable '@notation'. */ protected function getCollection($collection, $resolve = TRUE) { - return (object) array( - 'type' => 'collection', - 'value' => $collection, - 'resolve' => $resolve, - ); - } - - /** - * Helper function to return a service definition. - */ - protected function getParameterCall($name) { - return (object) array( - 'type' => 'parameter', - 'name' => $name, - ); + return $collection; } } - -} - -/* - * As Drupal Core does not ship with ExpressionLanguage component we need to - * define a dummy, else it cannot be tested. - */ -namespace Symfony\Component\ExpressionLanguage { - if (!class_exists('\Symfony\Component\ExpressionLanguage\Expression')) { - class Expression { - - /** - * Returns the expression as a String. - */ - public function __toString() { - return 'dummy_expression'; - } - } - } -} diff --git a/core/tests/Drupal/Tests/Core/DependencyInjection/PhpArray/Fixtures/container_test_file_service_test_service_function.data b/core/tests/Drupal/Tests/Core/DependencyInjection/Fixture/container_test_file_service_test_service_function.data similarity index 100% rename from core/tests/Drupal/Tests/Core/DependencyInjection/PhpArray/Fixtures/container_test_file_service_test_service_function.data rename to core/tests/Drupal/Tests/Core/DependencyInjection/Fixture/container_test_file_service_test_service_function.data diff --git a/core/tests/Drupal/Tests/Core/DependencyInjection/PhpArray/ContainerTest.php b/core/tests/Drupal/Tests/Core/DependencyInjection/PhpArray/ContainerTest.php deleted file mode 100644 index 27bc751..0000000 --- a/core/tests/Drupal/Tests/Core/DependencyInjection/PhpArray/ContainerTest.php +++ /dev/null @@ -1,1175 +0,0 @@ -machineFormat = TRUE; - $this->containerClass = '\Drupal\Core\DependencyInjection\Container'; - $this->containerDefinition = $this->getMockContainerDefinition(); - $this->container = new $this->containerClass($this->containerDefinition, TRUE); - } - - /** - * Tests that passing a non-supported format throws an InvalidArgumentException. - * @covers ::__construct - * - * @expectedException \Symfony\Component\DependencyInjection\Exception\InvalidArgumentException - */ - public function test_construct() { - $container_definition = $this->getMockContainerDefinition(); - $container_definition['machine_format'] = !$this->machineFormat; - $container = new $this->containerClass($container_definition, TRUE); - } - - - /** - * Tests that Container::getParameter() works properly. - * @covers ::getParameter - */ - public function test_getParameter() { - $this->assertEquals($this->containerDefinition['parameters']['some_config'], $this->container->getParameter('some_config'), 'Container parameter matches for %some_config%.'); - $this->assertEquals($this->containerDefinition['parameters']['some_other_config'], $this->container->getParameter('some_other_config'), 'Container parameter matches for %some_other_config%.'); - } - - /** - * Tests that Container::getParameter() works properly for non-existing - * parameters. - * - * @covers ::getParameter - * @covers ::getParameterAlternatives - * @covers ::getAlternatives - * - * @expectedException \Symfony\Component\DependencyInjection\Exception\ParameterNotFoundException - */ - public function test_getParameter_notFound() { - $this->container->getParameter('parameter_that_does_not_exist'); - } - - /** - * Tests that Container::getParameter() works properly for NULL parameters. - * - * @covers ::getParameter - * - * @expectedException \Symfony\Component\DependencyInjection\Exception\ParameterNotFoundException - */ - public function test_getParameter_notFound_null() { - $this->container->getParameter(NULL); - } - - /** - * Tests that Container::hasParameter() works properly. - * @covers ::hasParameter - */ - public function test_hasParameter() { - $this->assertTrue($this->container->hasParameter('some_config'), 'Container parameters include %some_config%.'); - $this->assertFalse($this->container->hasParameter('some_config_not_exists'), 'Container parameters do not include %some_config_not_exists%.'); - } - - /** - * Tests that Container::setParameter() in an unfrozen case works properly. - * - * @covers ::setParameter - */ - public function test_setParameter_unfrozenContainer() { - $this->container = new $this->containerClass($this->containerDefinition, FALSE); - $this->container->setParameter('some_config', 'new_value'); - $this->assertEquals('new_value', $this->container->getParameter('some_config'), 'Container parameters can be set.'); - } - - /** - * Tests that Container::setParameter() in a frozen case works properly. - * - * @covers ::setParameter - * - * @expectedException LogicException - */ - public function test_setParameter_frozenContainer() { - $this->container = new $this->containerClass($this->containerDefinition, TRUE); - $this->container->setParameter('some_config', 'new_value'); - } - - /** - * Tests that Container::get() works properly. - * - * @covers ::get - * @covers ::createService - */ - public function test_get() { - $container = $this->container->get('service_container'); - $this->assertSame($this->container, $container, 'Container can be retrieved from itself.'); - - // Retrieve services of the container. - $other_service_class = $this->containerDefinition['services']['other.service']['class']; - $other_service = $this->container->get('other.service'); - $this->assertInstanceOf($other_service_class, $other_service, 'other.service has the right class.'); - - $some_parameter = $this->containerDefinition['parameters']['some_config']; - $some_other_parameter = $this->containerDefinition['parameters']['some_other_config']; - - $service = $this->container->get('service.provider'); - - $this->assertEquals($other_service, $service->getSomeOtherService(), '@other.service was injected via constructor.'); - $this->assertEquals($some_parameter, $service->getSomeParameter(), '%some_config% was injected via constructor.'); - $this->assertEquals($this->container, $service->getContainer(), 'Container was injected via setter injection.'); - $this->assertEquals($some_other_parameter, $service->getSomeOtherParameter(), '%some_other_config% was injected via setter injection.'); - $this->assertEquals($service->_someProperty, 'foo', 'Service has added properties.'); - } - - /** - * Tests that Container::get() for non-shared services works properly. - * - * @covers ::get - * @covers ::createService - */ - public function test_get_nonShared() { - $service = $this->container->get('non_shared_service'); - $service2 = $this->container->get('non_shared_service'); - - $this->assertNotSame($service, $service2, 'Non shared services are always re-instantiated.'); - } - - /** - * Tests that Container::get() works properly for class from parameters. - * @covers ::get - * @covers ::createService - */ - public function test_get_classFromParameter() { - $container = new $this->containerClass($this->containerDefinition, FALSE); - - $other_service_class = $this->containerDefinition['parameters']['some_parameter_class']; - $other_service = $container->get('other.service_class_from_parameter'); - $this->assertInstanceOf($other_service_class, $other_service, 'other.service_class_from_parameter has the right class.'); - } - - /** - * Tests that Container::set() works properly. - * - * @covers ::set - */ - public function test_set() { - $this->assertNull($this->container->get('new_id', ContainerInterface::NULL_ON_INVALID_REFERENCE)); - $mock_service = new MockService(); - $this->container->set('new_id', $mock_service); - - $this->assertSame($mock_service, $this->container->get('new_id'), 'A manual set service works as expected.'); - } - - /** - * Tests that Container::has() works properly. - * - * @covers ::has - */ - public function test_has() { - $this->assertTrue($this->container->has('other.service')); - $this->assertFalse($this->container->has('another.service')); - - // Set the service manually, ensure that its also respected. - $mock_service = new MockService(); - $this->container->set('another.service', $mock_service); - $this->assertTrue($this->container->has('another.service')); - } - - /** - * Tests that Container::get() for circular dependencies works properly. - * @expectedException \Symfony\Component\DependencyInjection\Exception\ServiceCircularReferenceException - * @covers ::get - * @covers ::createService - */ - public function test_get_circular() { - $this->container->get('circular_dependency'); - } - - /** - * Tests that Container::get() for non-existant dependencies works properly. - * - * @covers ::get - * @covers ::createService - * @covers ::getAlternatives - * @covers ::getServiceAlternatives - * - * @expectedException \Symfony\Component\DependencyInjection\Exception\ServiceNotFoundException - */ - public function test_get_exception() { - $this->container->get('service_not_exists'); - } - - /** - * Tests that Container::get() for serialized definition works properly. - * @covers ::get - * @covers ::createService - */ - public function test_get_serializedDefinition() { - $container_definition = $this->containerDefinition; - $container_definition['services']['other.service'] = serialize($container_definition['services']['other.service']); - $container = new $this->containerClass($container_definition); - - // Retrieve services of the container. - $other_service_class = $this->containerDefinition['services']['other.service']['class']; - $other_service = $container->get('other.service'); - $this->assertInstanceOf($other_service_class, $other_service, 'other.service has the right class.'); - - $service = $container->get('service.provider'); - $this->assertEquals($other_service, $service->getSomeOtherService(), '@other.service was injected via constructor.'); - } - - - /** - * Tests that Container::get() for non-existant parameters works properly. - * @covers ::get - * @covers ::createService - * @covers ::resolveServicesAndParameters - */ - public function test_get_notFound_parameter() { - $service = $this->container->get('service_parameter_not_exists', ContainerInterface::NULL_ON_INVALID_REFERENCE); - $this->assertNull($service, 'Service is NULL.'); - } - - /** - * Tests Container::get() with an exception due to missing parameter on the second call. - * - * @covers ::get - * @covers ::createService - * @covers ::resolveServicesAndParameters - * - * @expectedException \Symfony\Component\DependencyInjection\Exception\InvalidArgumentException - */ - public function test_get_notFound_parameterWithExceptionOnSecondCall() { - $service = $this->container->get('service_parameter_not_exists', ContainerInterface::NULL_ON_INVALID_REFERENCE); - $this->assertNull($service, 'Service is NULL.'); - - // Reset the service. - $this->container->set('service_parameter_not_exists', NULL); - $this->container->get('service_parameter_not_exists'); - } - - /** - * Tests that Container::get() for non-existant parameters works properly. - * @expectedException \Symfony\Component\DependencyInjection\Exception\InvalidArgumentException - * @covers ::get - * @covers ::createService - * @covers ::resolveServicesAndParameters - */ - public function test_get_notFound_parameter_exception() { - $this->container->get('service_parameter_not_exists'); - } - - /** - * Tests that Container::get() for non-existent dependencies works properly. - * @covers ::get - * @covers ::createService - * @covers ::resolveServicesAndParameters - */ - public function test_get_notFound_dependency() { - $service = $this->container->get('service_dependency_not_exists', ContainerInterface::NULL_ON_INVALID_REFERENCE); - $this->assertNull($service, 'Service is NULL.'); - } - - /** - * Tests that Container::get() for non-existant dependencies works properly. - * @expectedException \Symfony\Component\DependencyInjection\Exception\ServiceNotFoundException - * @covers ::get - * @covers ::createService - * @covers ::resolveServicesAndParameters - * @covers ::getAlternatives - */ - public function test_get_notFound_dependency_exception() { - $this->container->get('service_dependency_not_exists'); - } - - - /** - * Tests that Container::get() for non-existant dependencies works properly. - * @covers ::get - * @covers ::createService - */ - public function test_get_notFound() { - $this->assertNull($this->container->get('service_not_exists', ContainerInterface::NULL_ON_INVALID_REFERENCE), 'Not found service does not throw exception.'); - } - - /** - * Tests that Container::get() for NULL service works properly. - * @covers ::get - * @covers ::createService - * - * @expectedException \Symfony\Component\DependencyInjection\Exception\ServiceNotFoundException - */ - public function test_get_notFound_NULL() { - $this->container->get(NULL); - } - - - /** - * Tests multiple Container::get() calls for non-existing dependencies work. - * - * @covers ::get - * @covers ::createService - */ - public function test_get_notFoundMultiple() { - $container = new $this->containerClass(); - - $this->assertNull($container->get('service_not_exists', ContainerInterface::NULL_ON_INVALID_REFERENCE, 'Not found service does not throw exception.')); - $this->assertNull($container->get('service_not_exists', ContainerInterface::NULL_ON_INVALID_REFERENCE, 'Not found service does not throw exception on second call.')); - } - - /** - * Tests multiple Container::get() calls with exception on the second time. - * - * @covers ::get - * @covers ::createService - * @covers ::getAlternatives - * - * @expectedException \Symfony\Component\DependencyInjection\Exception\ServiceNotFoundException - */ - public function test_get_notFoundMulitpleWithExceptionOnSecondCall() { - $this->assertNull($this->container->get('service_not_exists', ContainerInterface::NULL_ON_INVALID_REFERENCE, 'Not found service does nto throw exception.')); - $this->container->get('service_not_exists'); - } - - /** - * Tests that Container::get() for aliased services works properly. - * @covers ::get - * @covers ::createService - */ - public function test_get_alias() { - $service = $this->container->get('service.provider'); - $aliased_service = $this->container->get('service.provider_alias'); - $this->assertSame($service, $aliased_service); - } - - /** - * Tests that Container::get() for synthetic services works - if defined. - * - * @covers ::get - * @covers ::createService - */ - public function test_get_synthetic() { - $synthetic_service = new \stdClass(); - $this->container->set('synthetic', $synthetic_service); - $test_service = $this->container->get('synthetic'); - $this->assertSame($synthetic_service, $test_service); - } - - /** - * Tests that Container::get() for synthetic services throws an Exception if not defined. - * - * @covers ::get - * @covers ::createService - * - * @expectedException \Symfony\Component\DependencyInjection\Exception\RuntimeException - */ - public function test_get_synthetic_exception() { - $this->container->get('synthetic'); - } - - /** - * Tests that Container::get() for services with file includes works. - * - * @covers ::get - * @covers ::createService - */ - public function test_get_file() { - $file_service = $this->container->get('container_test_file_service_test'); - $this->assertTrue(function_exists('container_test_file_service_test_service_function')); - $this->assertEquals('Hello Container', container_test_file_service_test_service_function()); - } - - /** - * Tests that Container::get() for services with file includes works. - * - * @covers ::get - * @covers ::createService - * @covers ::resolveServicesAndParameters - */ - public function test_get_instantiation() { - $args = array(); - for ($i=0; $i < 12; $i++) { - $instantiation_service = $this->container->get('service_test_instantiation_'. $i); - $this->assertEquals($args, $instantiation_service->getArguments()); - $args[] = 'arg_' . $i; - } - } - - /** - * Tests that Container::get() for wrong factories works correctly. - * - * @covers ::get - * @covers ::createService - * - * @expectedException \Symfony\Component\DependencyInjection\Exception\RuntimeException - */ - public function test_get_factoryWrong() { - $this->container->get('wrong_factory'); - } - - /** - * Tests Container::get() for factories via services (Symfony 2.7.0). - * @covers ::get - * @covers ::createService - */ - public function test_get_factoryService() { - $factory_service = $this->container->get('factory_service'); - $factory_service_class = $this->container->getParameter('factory_service_class'); - $this->assertInstanceOf($factory_service_class, $factory_service); - } - - /** - * Tests that Container::get() for factories via class works (Symfony 2.7.0). - * @covers ::get - * @covers ::createService - */ - public function test_get_factoryClass() { - $service = $this->container->get('service.provider'); - $factory_service= $this->container->get('factory_class'); - - $this->assertInstanceOf(get_class($service), $factory_service); - $this->assertEquals('bar', $factory_service->getSomeParameter(), 'Correct parameter was passed via the factory class instantiation.'); - $this->assertEquals($this->container, $factory_service->getContainer(), 'Container was injected via setter injection.'); - } - - /** - * Tests that Container::get() for configurable services throws an Exception. - * - * @covers ::get - * @covers ::createService - * - * @expectedException \Symfony\Component\DependencyInjection\Exception\InvalidArgumentException - */ - public function test_get_configurator_exception() { - $this->container->get('configurable_service_exception'); - } - - /** - * Tests that Container::get() for configurable services works. - * @covers ::get - * @covers ::createService - */ - public function test_get_configurator() { - $container = $this->container; - - // Setup a configurator. - $configurator = $this->prophesize('\Drupal\Tests\Core\DependencyInjection\PhpArray\MockConfiguratorInterface'); - $configurator->configureService(Argument::type('object')) - ->shouldBeCalled(1) - ->will(function($args) use ($container) { - $args[0]->setContainer($container); - }); - $container->set('configurator', $configurator->reveal()); - - // Test that the configurator worked. - $service = $container->get('configurable_service'); - $this->assertSame($container, $service->getContainer(), 'Container was injected via configurator.'); - } - - /** - * Tests that private services work correctly. - * @covers ::get - * @covers ::createService - * @covers ::resolveServicesAndParameters - */ - public function test_resolveServicesAndParameters_privateService() { - $service = $this->container->get('service_using_private'); - $private_service = $service->getSomeOtherService(); - $this->assertEquals($private_service->getSomeParameter(), 'really_private_lama', 'Private was found successfully.'); - - // Test that sharing the same private services works. - $service = $this->container->get('another_service_using_private'); - $another_private_service = $service->getSomeOtherService(); - $this->assertNotSame($private_service, $another_private_service, 'Private service is not shared.'); - $this->assertEquals($private_service->getSomeParameter(), 'really_private_lama', 'Private was found successfully.'); - } - - /** - * Tests that private service sharing works correctly. - * - * @covers ::get - * @covers ::createService - * @covers ::resolveServicesAndParameters - */ - public function test_resolveServicesAndParameters_privateServiceShared() { - $service = $this->container->get('service_using_shared_private'); - $private_service = $service->getSomeOtherService(); - $this->assertEquals($private_service->getSomeParameter(), 'really_private_lama', 'Private was found successfully.'); - - // Test that sharing the same private services works. - $service = $this->container->get('another_service_using_shared_private'); - $same_private_service = $service->getSomeOtherService(); - $this->assertSame($private_service, $same_private_service, 'Private service is shared.'); - $this->assertEquals($private_service->getSomeParameter(), 'really_private_lama', 'Private was found successfully.'); - } - - /** - * Tests that services with an array of arguments work correctly. - * @covers ::get - * @covers ::createService - * @covers ::resolveServicesAndParameters - */ - public function test_resolveServicesAndParameters_array() { - $service = $this->container->get('service_using_array'); - $other_service = $this->container->get('other.service'); - $this->assertEquals($other_service, $service->getSomeOtherService(), '@other.service was injected via constructor.'); - } - - /** - * Tests that services that are optional work correctly. - * @covers ::get - * @covers ::createService - * @covers ::resolveServicesAndParameters - */ - public function test_resolveServicesAndParameters_optional() { - $service = $this->container->get('service_with_optional_dependency'); - $this->assertNull($service->getSomeOtherService(), 'other service was NULL was expected.'); - } - - /** - * Tests that an invalid argument throw an Exception. - * - * @covers ::get - * @covers ::createService - * @covers ::resolveServicesAndParameters - * - * @expectedException \Symfony\Component\DependencyInjection\Exception\InvalidArgumentException - */ - public function test_resolveServicesAndParameters_invalidArgument() { - $this->container->get('invalid_argument_service'); - } - - /** - * Tests that invalid arguments throw an Exception. - * - * @covers ::get - * @covers ::createService - * @covers ::resolveServicesAndParameters - * - * @expectedException \Symfony\Component\DependencyInjection\Exception\InvalidArgumentException - */ - public function test_resolveServicesAndParameters_invalidArguments() { - // In case the machine format is not used, we need to simulate the test failure. - if (!$this->machineFormat) { - throw new \Symfony\Component\DependencyInjection\Exception\InvalidArgumentException('Simulating the test failure.'); - } - $this->container->get('invalid_arguments_service'); - } - - /** - * Tests that a parameter that points to a service works correctly. - * - * @covers ::get - * @covers ::createService - * @covers ::resolveServicesAndParameters - */ - public function test_resolveServicesAndParameters_fromParameter() { - $service = $this->container->get('service.provider'); - $test_service = $this->container->get('service_with_parameter_service'); - $this->assertSame($service, $test_service->getSomeOtherService(), 'Service was passed via parameter.'); - } - - - /** - * Tests that Container::initialized works correctly. - * @covers ::initialized - */ - public function test_initialized() { - $this->assertFalse($this->container->initialized('late.service'), 'Late service is not initialized.'); - $this->container->get('late.service'); - $this->assertTrue($this->container->initialized('late.service'), 'Late service is initialized after it was retrieved once.'); - } - - /** - * Tests that Container::initialized works correctly for aliases. - * @covers ::initialized - */ - public function test_initialized_aliases() { - $this->assertFalse($this->container->initialized('late.service_alias'), 'Late service is not initialized.'); - $this->container->get('late.service'); - $this->assertTrue($this->container->initialized('late.service_alias'), 'Late service is initialized after it was retrieved once.'); - } - - /** - * Tests that unsupported methods throw an Exception. - * - * @covers ::enterScope - * @covers ::leaveScope - * @covers ::addScope - * @covers ::hasScope - * @covers ::isScopeActive - * - * @expectedException \BadMethodCallException - * - * @dataProvider scopeExceptionTestProvider - */ - public function test_scope_exception($method, $argument) { - $callable = array( - $this->container, - $method, - ); - - $callable($argument); - } - - /** - * Data provider for test_scope_exception(). - * - * @return array[] - * Returns per data set an array with: - * - method name to call - * - argument to pass - */ - public function scopeExceptionTestProvider() { - $scope = $this->prophesize('\Symfony\Component\DependencyInjection\ScopeInterface')->reveal(); - return array( - array('enterScope', 'test_scope'), - array('leaveScope', 'test_scope'), - array('hasScope', 'test_scope'), - array('isScopeActive', 'test_scope'), - array('addScope', $scope), - ); - } - - /** - * Tests that __sleep throws an Exception. - * - * @covers ::__sleep - * - * @expectedException \PHPUnit_Framework_Error - */ - public function test_sleep() { - $serialized = serialize($this->container); - } - - /** - * Tests that __sleep works when error handler is set to non-fatal. - * - * @covers ::__sleep - */ - public function test_sleep_working() { - $container = new $this->containerClass(); - - // Ignore any errors. - set_error_handler(array($this, 'ignoreErrorHandler')); - $serialized = serialize($container); - restore_error_handler(); - } - - /** - * An error handler that ignores all errors. - */ - public function ignoreErrorHandler() { - } - - /** - * Returns a mock container definition. - * - * @return array - * Associated array with parameters and services. - */ - protected function getMockContainerDefinition() { - $fake_service = new \stdClass(); - $parameters = array(); - $parameters['some_parameter_class'] = get_class($fake_service); - $parameters['some_private_config'] = 'really_private_lama'; - $parameters['some_config'] = 'foo'; - $parameters['some_other_config'] = 'lama'; - $parameters['factory_service_class'] = get_class($fake_service); - // Also test alias resolving. - $parameters['service_from_parameter'] = $this->getServiceCall('service.provider_alias'); - - $services = array(); - $services['service_container'] = array( - 'class' => '\Drupal\service_container\DependencyInjection\Container', - ); - $services['other.service'] = array( - 'class' => get_class($fake_service), - ); - - $services['non_shared_service'] = array( - 'class' => get_class($fake_service), - 'shared' => FALSE, - ); - - $services['other.service_class_from_parameter'] = array( - 'class' => $this->getParameterCall('some_parameter_class'), - ); - $services['late.service'] = array( - 'class' => get_class($fake_service), - ); - $services['service.provider'] = array( - 'class' => '\Drupal\Tests\Core\DependencyInjection\PhpArray\MockService', - 'arguments' => $this->getCollection(array( - $this->getServiceCall('other.service'), - $this->getParameterCall('some_config'), - )), - 'properties' => $this->getCollection(array('_someProperty' => 'foo')), - 'calls' => array( - array('setContainer', $this->getCollection(array( - $this->getServiceCall('service_container'), - ))), - array('setOtherConfigParameter', $this->getCollection(array( - $this->getParameterCall('some_other_config'), - ))), - ), - 'priority' => 0, - ); - - // Test private services. - - $private_service = array( - 'class' => '\Drupal\Tests\Core\DependencyInjection\PhpArray\MockService', - 'arguments' => $this->getCollection(array( - $this->getServiceCall('other.service'), - $this->getParameterCall('some_private_config'), - )), - 'public' => FALSE, - ); - - $services['service_using_private'] = array( - 'class' => '\Drupal\Tests\Core\DependencyInjection\PhpArray\\MockService', - 'arguments' => $this->getCollection(array( - $this->getPrivateServiceCall(NULL, $private_service), - $this->getParameterCall('some_config'), - )), - ); - $services['another_service_using_private'] = array( - 'class' => '\Drupal\Tests\Core\DependencyInjection\PhpArray\\MockService', - 'arguments' => $this->getCollection(array( - $this->getPrivateServiceCall(NULL, $private_service), - $this->getParameterCall('some_config'), - )), - ); - - // Test shared private services. - - $id = 'private_service_shared_1'; - - $services['service_using_shared_private'] = array( - 'class' => '\Drupal\Tests\Core\DependencyInjection\PhpArray\\MockService', - 'arguments' => $this->getCollection(array( - $this->getPrivateServiceCall($id, $private_service, TRUE), - $this->getParameterCall('some_config'), - )), - ); - $services['another_service_using_shared_private'] = array( - 'class' => '\Drupal\Tests\Core\DependencyInjection\PhpArray\\MockService', - 'arguments' => $this->getCollection(array( - $this->getPrivateServiceCall($id, $private_service, TRUE), - $this->getParameterCall('some_config'), - )), - ); - - // Tests service with invalid argument. - $services['invalid_argument_service'] = array( - 'class' => '\Drupal\Tests\Core\DependencyInjection\PhpArray\\MockService', - 'arguments' => $this->getCollection(array( - 1, // Test passing non-strings, too. - (object) array( - 'type' => 'invalid', - ), - )), - ); - - $services['invalid_arguments_service'] = array( - 'class' => '\Drupal\Tests\Core\DependencyInjection\PhpArray\\MockService', - 'arguments' => (object) array( - 'type' => 'invalid', - ), - ); - - // Test service that needs deep-traversal. - $services['service_using_array'] = array( - 'class' => '\Drupal\Tests\Core\DependencyInjection\PhpArray\MockService', - 'arguments' => $this->getCollection(array( - $this->getCollection(array( - $this->getServiceCall('other.service'), - )), - $this->getParameterCall('some_private_config'), - )), - ); - - $services['service_with_optional_dependency'] = array( - 'class' => '\Drupal\Tests\Core\DependencyInjection\PhpArray\MockService', - 'arguments' => $this->getCollection(array( - $this->getServiceCall('service.does_not_exist', ContainerInterface::NULL_ON_INVALID_REFERENCE), - $this->getParameterCall('some_private_config'), - )), - - ); - - $services['factory_service'] = array( - 'class' => '\Drupal\service_container\ServiceContainer\ControllerInterface', - 'factory' => array( - $this->getServiceCall('service.provider'), - 'getFactoryMethod', - ), - 'arguments' => $this->getCollection(array( - $this->getParameterCall('factory_service_class'), - )), - ); - $services['factory_class'] = array( - 'class' => '\Drupal\service_container\ServiceContainer\ControllerInterface', - 'factory' => '\Drupal\Tests\Core\DependencyInjection\PhpArray\MockService::getFactoryMethod', - 'arguments' => array( - '\Drupal\Tests\Core\DependencyInjection\PhpArray\MockService', - array(NULL, 'bar'), - ), - 'calls' => array( - array('setContainer', $this->getCollection(array( - $this->getServiceCall('service_container'), - ))), - ), - ); - - $services['wrong_factory'] = array( - 'class' => '\Drupal\service_container\ServiceContainer\ControllerInterface', - 'factory' => (object) array('I am not a factory, but I pretend to be.'), - ); - - $services['circular_dependency'] = array( - 'class' => '\Drupal\Tests\Core\DependencyInjection\PhpArray\MockService', - 'arguments' => $this->getCollection(array( - $this->getServiceCall('circular_dependency'), - )), - ); - $services['synthetic'] = array( - 'synthetic' => TRUE, - ); - $services['container_test_file_service_test'] = array( - 'class' => '\stdClass', - 'file' => __DIR__ . '/Fixtures/container_test_file_service_test_service_function.data', - ); - - // Test multiple arguments. - $args = array(); - for ($i=0; $i < 12; $i++) { - $services['service_test_instantiation_' . $i] = array( - 'class' => '\Drupal\Tests\Core\DependencyInjection\PhpArray\MockInstantiationService', - // Also test a collection that does not need resolving. - 'arguments' => $this->getCollection($args, FALSE), - ); - $args[] = 'arg_' . $i; - } - - $services['service_parameter_not_exists'] = array( - 'class' => '\Drupal\Tests\Core\DependencyInjection\PhpArray\MockService', - 'arguments' => $this->getCollection(array( - $this->getServiceCall('service.provider'), - $this->getParameterCall('not_exists'), - )), - ); - $services['service_dependency_not_exists'] = array( - 'class' => '\Drupal\Tests\Core\DependencyInjection\PhpArray\MockService', - 'arguments' => $this->getCollection(array( - $this->getServiceCall('service_not_exists'), - $this->getParameterCall('some_config'), - )), - ); - - $services['service_with_parameter_service'] = array( - 'class' => '\Drupal\Tests\Core\DependencyInjection\PhpArray\MockService', - 'arguments' => $this->getCollection(array( - $this->getParameterCall('service_from_parameter'), - // Also test deep collections that don't need resolving. - $this->getCollection(array( - 1, - ), FALSE), - )), - ); - - // To ensure getAlternatives() finds something. - $services['service_not_exists_similar'] = array( - 'synthetic' => TRUE, - ); - - // Test configurator. - $services['configurator'] = array( - 'synthetic' => TRUE, - ); - $services['configurable_service'] = array( - 'class' => '\Drupal\Tests\Core\DependencyInjection\PhpArray\MockService', - 'arguments' => array(), - 'configurator' => array( - $this->getServiceCall('configurator'), - 'configureService' - ), - ); - $services['configurable_service_exception'] = array( - 'class' => '\Drupal\Tests\Core\DependencyInjection\PhpArray\MockService', - 'arguments' => array(), - 'configurator' => 'configurator_service_test_does_not_exist', - ); - - $aliases = array(); - $aliases['service.provider_alias'] = 'service.provider'; - $aliases['late.service_alias'] = 'late.service'; - - return array( - 'aliases' => $aliases, - 'parameters' => $parameters, - 'services' => $services, - 'machine_format' => $this->machineFormat, - ); - } - - /** - * Helper function to return a service definition. - */ - protected function getServiceCall($id, $invalid_behavior = ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE) { - return (object) array( - 'type' => 'service', - 'id' => $id, - 'invalidBehavior' => $invalid_behavior, - ); - } - - /** - * Helper function to return a service definition. - */ - protected function getParameterCall($name) { - return (object) array( - 'type' => 'parameter', - 'name' => $name, - ); - } - - /** - * Helper function to return a private service definition. - */ - protected function getPrivateServiceCall($id, $service_definition, $shared = FALSE) { - if (!$id) { - $hash = sha1(serialize($service_definition)); - $id = 'private__' . $hash; - } - return (object) array( - 'type' => 'private_service', - 'id' => $id, - 'value' => $service_definition, - 'shared' => $shared, - ); - } - - /** - * Helper function to return a machine readable collection. - */ - protected function getCollection($collection, $resolve = TRUE) { - return (object) array( - 'type' => 'collection', - 'value' => $collection, - 'resolve' => $resolve, - ); - } - -} - -/** - * Helper interface to test Container::get() with configurator. - * - * @group container - */ -interface MockConfiguratorInterface { - - /** - * Configures a service. - * - * @param object $service - * The service to configure. - */ - public function configureService($service); - -} - - -/** - * Helper class to test Container::get() method for varying number of parameters. - * - * @group container - */ -class MockInstantiationService { - - /** - * @var mixed[] - */ - protected $arguments; - - /** - * Construct a mock instantiation service. - */ - public function __construct() { - $this->arguments = func_get_args(); - } - - /** - * Return arguments injected into the service. - * - * @return mixed[] - * Return the passed arguments. - */ - public function getArguments() { - return $this->arguments; - } - -} - - -/** - * Helper class to test Container::get() method. - * - * @group container - */ -class MockService { - - /** - * @var ContainerInterface - */ - protected $container; - - /** - * @var object - */ - protected $someOtherService; - - /** - * @var string - */ - protected $someParameter; - - /** - * @var string - */ - protected $someOtherParameter; - - /** - * Constructs a MockService object. - * - * @param object $some_other_service - * (optional) Another injected service. - * @param string $some_parameter - * (optional) An injected parameter. - */ - public function __construct($some_other_service = NULL, $some_parameter = NULL) { - if (is_array($some_other_service)) { - $some_other_service = $some_other_service[0]; - } - $this->someOtherService = $some_other_service; - $this->someParameter = $some_parameter; - } - - /** - * Sets the container object. - * - * @param ContainerInterface $container - * The container to inject via setter injection. - */ - public function setContainer(ContainerInterface $container) { - $this->container = $container; - } - - /** - * Gets the container object. - * - * @return ContainerInterface - * The internally set container. - */ - public function getContainer() { - return $this->container; - } - - /** - * Gets the someOtherService object. - * - * @return object - * The injected service. - */ - public function getSomeOtherService() { - return $this->someOtherService; - } - - /** - * Gets the someParameter property. - * - * @return string - * The injected parameter. - */ - public function getSomeParameter() { - return $this->someParameter; - } - - /** - * Sets the someOtherParameter property. - * - * @param string $some_other_parameter - * The setter injected parameter. - */ - public function setOtherConfigParameter($some_other_parameter) { - $this->someOtherParameter = $some_other_parameter; - } - - /** - * Gets the someOtherParameter property. - * - * @return string - * The injected parameter. - */ - public function getSomeOtherParameter() { - return $this->someOtherParameter; - } - - /** - * Provides a factory method to get a service. - * - * @param string $class - * The class name of the class to instantiate - * @param array $arguments - * (optional) Arguments to pass to the new class. - * - * @return object - * The instantiated service object. - */ - public static function getFactoryMethod($class, $arguments = array()) { - $r = new \ReflectionClass($class); - $service = ($r->getConstructor() === NULL) ? $r->newInstance() : $r->newInstanceArgs($arguments); - - return $service; - } - -} diff --git a/core/tests/Drupal/Tests/Core/DependencyInjection/PhpArray/BootstrapContainerTest.php b/core/tests/Drupal/Tests/Core/DependencyInjection/PhpArrayContainerTest.php similarity index 73% rename from core/tests/Drupal/Tests/Core/DependencyInjection/PhpArray/BootstrapContainerTest.php rename to core/tests/Drupal/Tests/Core/DependencyInjection/PhpArrayContainerTest.php index ae5448c..f4f309c 100644 --- a/core/tests/Drupal/Tests/Core/DependencyInjection/PhpArray/BootstrapContainerTest.php +++ b/core/tests/Drupal/Tests/Core/DependencyInjection/PhpArrayContainerTest.php @@ -2,23 +2,23 @@ /** * @file - * Contains \Drupal\Tests\Core\DependencyInjection\PhpArray\BootstrapContainerTest. + * Contains \Drupal\Tests\Core\DependencyInjection\PhpArrayContainerTest. */ -namespace Drupal\Tests\Core\DependencyInjection\PhpArray; +namespace Drupal\Tests\Core\DependencyInjection; use Symfony\Component\DependencyInjection\ContainerInterface; use Symfony\Component\DependencyInjection\Exception\LogicException; /** - * @coversDefaultClass \Drupal\Core\DependencyInjection\BootstrapContainer - * @group container + * @coversDefaultClass \Drupal\Core\DependencyInjection\PhpArrayContainer + * @group DependencyInjection */ -class BootstrapContainerTest extends ContainerTest { +class PhpArrayContainerTest extends ContainerTest { public function setUp() { $this->machineFormat = FALSE; - $this->containerClass = '\Drupal\Core\DependencyInjection\BootstrapContainer'; + $this->containerClass = '\Drupal\Core\DependencyInjection\PhpArrayContainer'; $this->containerDefinition = $this->getMockContainerDefinition(); $this->container = new $this->containerClass($this->containerDefinition); }