Inheritance: extends Nette\Object
示例#1
0
 private function updateDefinition(DI\ServiceDefinition $def)
 {
     $class = $def->getClass();
     $setups = $def->getSetup();
     foreach (self::getInjectProperties($class) as $property => $type) {
         $builder = $this->getContainerBuilder();
         $inject = new DI\Statement('$' . $property, ['@\\' . ltrim($type, '\\')]);
         foreach ($setups as $key => $setup) {
             if ($setup->getEntity() === $inject->getEntity()) {
                 $inject = $setup;
                 $builder = NULL;
                 unset($setups[$key]);
             }
         }
         self::checkType($class, $property, $type, $builder);
         array_unshift($setups, $inject);
     }
     foreach (array_reverse(self::getInjectMethods($def->getClass())) as $method) {
         $inject = new DI\Statement($method);
         foreach ($setups as $key => $setup) {
             if ($setup->getEntity() === $inject->getEntity()) {
                 $inject = $setup;
                 unset($setups[$key]);
             }
         }
         array_unshift($setups, $inject);
     }
     $def->setSetup($setups);
 }
示例#2
0
 /**
  * Formats PHP code for class instantiating, function calling or property setting in PHP.
  * @return string
  * @internal
  */
 public function formatStatement(Statement $statement)
 {
     $entity = $this->normalizeEntity($statement->getEntity());
     $arguments = $statement->arguments;
     if (is_string($entity) && Strings::contains($entity, '?')) {
         // PHP literal
         return $this->formatPhp($entity, $arguments);
     } elseif ($service = $this->getServiceName($entity)) {
         // factory calling
         $params = [];
         foreach ($this->definitions[$service]->parameters as $k => $v) {
             $params[] = preg_replace('#\\w+\\z#', '\\$$0', is_int($k) ? $v : $k) . (is_int($k) ? '' : ' = ' . PhpHelpers::dump($v));
         }
         $rm = new \ReflectionFunction(create_function(implode(', ', $params), ''));
         $arguments = Helpers::autowireArguments($rm, $arguments, $this);
         return $this->formatPhp('$this->?(?*)', [Container::getMethodName($service), $arguments]);
     } elseif ($entity === 'not') {
         // operator
         return $this->formatPhp('!?', [$arguments[0]]);
     } elseif (is_string($entity)) {
         // class name
         if ($constructor = (new ReflectionClass($entity))->getConstructor()) {
             $this->addDependency((string) $constructor->getFileName());
             $arguments = Helpers::autowireArguments($constructor, $arguments, $this);
         } elseif ($arguments) {
             throw new ServiceCreationException("Unable to pass arguments, class {$entity} has no constructor.");
         }
         return $this->formatPhp("new {$entity}" . ($arguments ? '(?*)' : ''), [$arguments]);
     } elseif (!Nette\Utils\Arrays::isList($entity) || count($entity) !== 2) {
         throw new ServiceCreationException(sprintf('Expected class, method or property, %s given.', PhpHelpers::dump($entity)));
     } elseif (!preg_match('#^\\$?' . PhpHelpers::PHP_IDENT . '\\z#', $entity[1])) {
         throw new ServiceCreationException("Expected function, method or property name, '{$entity['1']}' given.");
     } elseif ($entity[0] === '') {
         // globalFunc
         return $this->formatPhp("{$entity['1']}(?*)", [$arguments]);
     } elseif ($entity[0] instanceof Statement) {
         $inner = $this->formatPhp('?', [$entity[0]]);
         if (substr($inner, 0, 4) === 'new ') {
             $inner = "({$inner})";
         }
         return $this->formatPhp("{$inner}->?(?*)", [$entity[1], $arguments]);
     } elseif (Strings::contains($entity[1], '$')) {
         // property setter
         Validators::assert($arguments, 'list:1', "setup arguments for '" . Nette\Utils\Callback::toString($entity) . "'");
         if ($this->getServiceName($entity[0])) {
             return $this->formatPhp('?->? = ?', [$entity[0], substr($entity[1], 1), $arguments[0]]);
         } else {
             return $this->formatPhp($entity[0] . '::$? = ?', [substr($entity[1], 1), $arguments[0]]);
         }
     } elseif ($service = $this->getServiceName($entity[0])) {
         // service method
         $class = $this->definitions[$service]->getImplement();
         if (!$class || !method_exists($class, $entity[1])) {
             $class = $this->definitions[$service]->getClass();
         }
         if ($class) {
             $arguments = $this->autowireArguments($class, $entity[1], $arguments);
         }
         return $this->formatPhp('?->?(?*)', [$entity[0], $entity[1], $arguments]);
     } else {
         // static method
         $arguments = $this->autowireArguments($entity[0], $entity[1], $arguments);
         return $this->formatPhp("{$entity['0']}::{$entity['1']}(?*)", [$arguments]);
     }
 }
示例#3
0
 public function getEntity()
 {
     return $this->factory ? $this->factory->getEntity() : NULL;
 }
示例#4
0
 /**
  * @param \Nette\DI\ServiceDefinition $metadataDriver
  * @param string $namespace
  * @param string|object $driver
  * @param string $prefix
  * @throws \Nette\Utils\AssertionException
  * @return string
  */
 protected function processMetadataDriver(Nette\DI\ServiceDefinition $metadataDriver, $namespace, $driver, $prefix)
 {
     if (!is_string($namespace) || !Strings::match($namespace, '#^' . self::PHP_NAMESPACE . '\\z#')) {
         throw new Nette\Utils\AssertionException("The metadata namespace expects to be valid namespace, {$namespace} given.");
     }
     $namespace = ltrim($namespace, '\\');
     if (is_string($driver) || is_array($driver)) {
         $paths = is_array($driver) ? $driver : [$driver];
         foreach ($paths as $path) {
             if (($pos = strrpos($path, '*')) !== FALSE) {
                 $path = substr($path, 0, $pos);
             }
             if (!file_exists($path)) {
                 throw new Nette\Utils\AssertionException("The metadata path expects to be an existing directory, {$path} given.");
             }
         }
         $driver = new Statement(self::ANNOTATION_DRIVER, is_array($paths) ? $paths : [$paths]);
     }
     $impl = $driver instanceof \stdClass ? $driver->value : ($driver instanceof Statement ? $driver->getEntity() : (string) $driver);
     list($driver) = CacheHelpers::filterArgs($driver);
     /** @var Statement $driver */
     /** @var string $impl */
     if (isset($this->metadataDriverClasses[$impl])) {
         $driver = new Statement($this->metadataDriverClasses[$impl], $driver->arguments);
     }
     if (is_string($driver->getEntity()) && substr($driver->getEntity(), 0, 1) === '@') {
         $metadataDriver->addSetup('addDriver', [$driver->getEntity(), $namespace]);
         return $driver->getEntity();
     }
     if ($impl === self::ANNOTATION_DRIVER) {
         $driver->arguments = [Nette\Utils\Arrays::flatten($driver->arguments), 2 => $this->prefix('@cache.' . $prefix . '.metadata')];
     }
     $serviceName = $this->prefix($prefix . '.driver.' . str_replace('\\', '_', $namespace) . '.' . str_replace('\\', '_', $impl) . 'Impl');
     $this->getContainerBuilder()->addDefinition($serviceName)->setClass('Doctrine\\Common\\Persistence\\Mapping\\Driver\\MappingDriver')->setFactory($driver->getEntity(), $driver->arguments)->setAutowired(FALSE)->setInject(FALSE);
     $metadataDriver->addSetup('addDriver', ['@' . $serviceName, $namespace]);
     return '@' . $serviceName;
 }
示例#5
0
文件: PhpGenerator.php 项目: nette/di
 /**
  * Formats PHP code for class instantiating, function calling or property setting in PHP.
  * @return string
  */
 private function formatStatement(Statement $statement)
 {
     $entity = $statement->getEntity();
     $arguments = $statement->arguments;
     if (is_string($entity) && Strings::contains($entity, '?')) {
         // PHP literal
         return $this->formatPhp($entity, $arguments);
     } elseif ($service = $this->builder->getServiceName($entity)) {
         // factory calling
         return $this->formatPhp('$this->?(?*)', [Container::getMethodName($service), $arguments]);
     } elseif ($entity === 'not') {
         // operator
         return $this->formatPhp('!?', [$arguments[0]]);
     } elseif (is_string($entity)) {
         // class name
         return $this->formatPhp("new {$entity}" . ($arguments ? '(?*)' : ''), [$arguments]);
     } elseif ($entity[0] === '') {
         // globalFunc
         return $this->formatPhp("{$entity['1']}(?*)", [$arguments]);
     } elseif ($entity[0] instanceof Statement) {
         $inner = $this->formatPhp('?', [$entity[0]]);
         if (substr($inner, 0, 4) === 'new ') {
             $inner = "({$inner})";
         }
         return $this->formatPhp("{$inner}->?(?*)", [$entity[1], $arguments]);
     } elseif ($entity[1][0] === '$') {
         // property getter, setter or appender
         $name = substr($entity[1], 1);
         if ($append = substr($name, -2) === '[]') {
             $name = substr($name, 0, -2);
         }
         if ($this->builder->getServiceName($entity[0])) {
             $prop = $this->formatPhp('?->?', [$entity[0], $name]);
         } else {
             $prop = $this->formatPhp($entity[0] . '::$?', [$name]);
         }
         return $arguments ? $this->formatPhp($prop . ($append ? '[]' : '') . ' = ?', [$arguments[0]]) : $prop;
     } elseif ($service = $this->builder->getServiceName($entity[0])) {
         // service method
         return $this->formatPhp('?->?(?*)', [$entity[0], $entity[1], $arguments]);
     } else {
         // static method
         return $this->formatPhp("{$entity['0']}::{$entity['1']}(?*)", [$arguments]);
     }
 }
示例#6
0
 /**
  * @return Statement
  */
 public function completeStatement(Statement $statement)
 {
     $entity = $this->normalizeEntity($statement->getEntity());
     $arguments = $statement->arguments;
     if (is_string($entity) && Strings::contains($entity, '?')) {
         // PHP literal
     } elseif ($service = $this->getServiceName($entity)) {
         // factory calling
         $params = [];
         foreach ($this->definitions[$service]->parameters as $k => $v) {
             $params[] = preg_replace('#\\w+\\z#', '\\$$0', is_int($k) ? $v : $k) . (is_int($k) ? '' : ' = ' . PhpHelpers::dump($v));
         }
         $rm = new \ReflectionFunction(create_function(implode(', ', $params), ''));
         $arguments = Helpers::autowireArguments($rm, $arguments, $this);
         $entity = '@' . $service;
     } elseif ($entity === 'not') {
         // operator
     } elseif (is_string($entity)) {
         // class name
         if (!class_exists($entity)) {
             throw new ServiceCreationException("Class {$entity} not found.");
         } elseif ((new ReflectionClass($entity))->isAbstract()) {
             throw new ServiceCreationException("Class {$entity} is abstract.");
         } elseif (($rm = (new ReflectionClass($entity))->getConstructor()) !== NULL && !$rm->isPublic()) {
             $visibility = $rm->isProtected() ? 'protected' : 'private';
             throw new ServiceCreationException("Class {$entity} has {$visibility} constructor.");
         } elseif ($constructor = (new ReflectionClass($entity))->getConstructor()) {
             $this->addDependency($constructor);
             $arguments = Helpers::autowireArguments($constructor, $arguments, $this);
         } elseif ($arguments) {
             throw new ServiceCreationException("Unable to pass arguments, class {$entity} has no constructor.");
         }
     } elseif (!Nette\Utils\Arrays::isList($entity) || count($entity) !== 2) {
         throw new ServiceCreationException(sprintf('Expected class, method or property, %s given.', PhpHelpers::dump($entity)));
     } elseif (!preg_match('#^\\$?' . PhpHelpers::PHP_IDENT . '(\\[\\])?\\z#', $entity[1])) {
         throw new ServiceCreationException("Expected function, method or property name, '{$entity['1']}' given.");
     } elseif ($entity[0] === '') {
         // globalFunc
         if (!Nette\Utils\Arrays::isList($arguments)) {
             throw new ServiceCreationException("Unable to pass specified arguments to {$entity['0']}.");
         } elseif (!function_exists($entity[1])) {
             throw new ServiceCreationException("Function {$entity['1']} doesn't exist.");
         }
         $rf = new \ReflectionFunction($entity[1]);
         $this->addDependency($rf);
         $arguments = Helpers::autowireArguments($rf, $arguments, $this);
     } else {
         if ($entity[0] instanceof Statement) {
             $entity[0] = $this->completeStatement($entity[0]);
         } elseif ($service = $this->getServiceName($entity[0])) {
             // service method
             $entity[0] = '@' . $service;
         }
         if ($entity[1][0] === '$') {
             // property getter, setter or appender
             Validators::assert($arguments, 'list:0..1', "setup arguments for '" . Nette\Utils\Callback::toString($entity) . "'");
             if (!$arguments && substr($entity[1], -2) === '[]') {
                 throw new ServiceCreationException("Missing argument for {$entity['1']}.");
             }
         } elseif ($class = empty($service) || $entity[1] === 'create' ? $this->resolveEntityClass($entity[0]) : $this->definitions[$service]->getClass()) {
             $arguments = $this->autowireArguments($class, $entity[1], $arguments);
         }
     }
     array_walk_recursive($arguments, function (&$val) {
         if ($val instanceof Statement) {
             $val = $this->completeStatement($val);
         } elseif ($val === $this) {
             trigger_error("Replace object ContainerBuilder in Statement arguments with '@container'.", E_USER_DEPRECATED);
             $val = self::literal('$this');
         } elseif ($val instanceof ServiceDefinition) {
             $val = '@' . current(array_keys($this->getDefinitions(), $val, TRUE));
         } elseif (is_string($val) && strlen($val) > 1 && $val[0] === '@' && $val[1] !== '@') {
             $pair = explode('::', $val, 2);
             $name = $this->getServiceName($pair[0]);
             if (!isset($pair[1])) {
                 // @service
                 $val = '@' . $name;
             } elseif (preg_match('#^[A-Z][A-Z0-9_]*\\z#', $pair[1], $m)) {
                 // @service::CONSTANT
                 $val = self::literal($this->getDefinition($name)->getClass() . '::' . $pair[1]);
             } else {
                 // @service::property
                 $val = new Statement(['@' . $name, '$' . $pair[1]]);
             }
         }
     });
     return new Statement($entity, $arguments);
 }