/** * Generates body of service method. * @return string */ private function generateService($name) { $def = $this->builder->getDefinition($name); if ($def->isDynamic()) { return PhpHelpers::formatArgs('throw new Nette\\DI\\ServiceCreationException(?);', ["Unable to create dynamic service '{$name}', it must be added using addService()"]); } $entity = $def->getFactory()->getEntity(); $serviceRef = $this->builder->getServiceName($entity); $factory = $serviceRef && !$def->getFactory()->arguments && !$def->getSetup() && $def->getImplementMode() !== $def::IMPLEMENT_MODE_CREATE ? new Statement(['@' . ContainerBuilder::THIS_CONTAINER, 'getService'], [$serviceRef]) : $def->getFactory(); $this->currentService = NULL; $code = '$service = ' . $this->formatStatement($factory) . ";\n"; if (($class = $def->getClass()) && !$serviceRef && $class !== $entity && !(is_string($entity) && preg_match('#^[\\w\\\\]+\\z#', $entity) && is_subclass_of($entity, $class))) { $code .= PhpHelpers::formatArgs("if (!\$service instanceof {$class}) {\n" . "\tthrow new Nette\\UnexpectedValueException(?);\n}\n", ["Unable to create service '{$name}', value returned by factory is not {$class} type."]); } $this->currentService = $name; foreach ($def->getSetup() as $setup) { $code .= $this->formatStatement($setup) . ";\n"; } $code .= 'return $service;'; if (!$def->getImplement()) { return $code; } $factoryClass = new Nette\PhpGenerator\ClassType(); $factoryClass->setName('($this)')->addImplement($def->getImplement()); $factoryClass->addProperty('container')->setVisibility('private'); $factoryClass->addMethod('__construct')->addBody('$this->container = $container;')->addParameter('container')->setTypeHint($this->className); $factoryClass->addMethod($def->getImplementMode())->setParameters($this->convertParameters($def->parameters))->setBody(str_replace('$this', '$this->container', $code))->setReturnType(PHP_VERSION_ID >= 70000 ? $def->getClass() : NULL); if (PHP_VERSION_ID < 70000) { $this->generatedClasses[] = $factoryClass; $factoryClass->setName(str_replace(['\\', '.'], '_', "{$this->className}_{$def->getImplement()}Impl_{$name}")); return "return new {$factoryClass->getName()}(\$this);"; } return 'return new ' . rtrim($factoryClass) . ';'; }
/** * Routes definition * * @param ContainerBuilder $container Container * @param array $config Config * * @return void */ protected function loadRoutes(ContainerBuilder $container, $config) { $container->addDefinition($this->prefix('storages'))->setClass('MouseOver\\Storage\\Application\\StorageList'); $container->addDefinition($this->prefix('responder'))->setClass('MouseOver\\Storage\\Application\\StorageResponder'); $container->addDefinition($this->prefix('linkResolver'))->setClass('MouseOver\\Storage\\Application\\StorageLinkResolver', [$config['module']]); $container->getDefinition('nette.latte')->addSetup('MouseOver\\Storage\\Application\\StorageMacros::install($service->getCompiler(), ?)', array($this->prefix('@linkResolver'))); $routesList = $container->addDefinition($this->prefix('storageRoutes'))->setClass('Nette\\Application\\Routers\\RouteList')->setAutowired(false); $routesList->addSetup('$service[] = new Nette\\Application\\Routers\\Route(?, function ($presenter, $storage, $file) { return ?->handle($storage, $file, $presenter->request->getParameters()); })', array($config['module'] . '/<storage>/<file [a-zA-Z0-9\\-_.\\/]+>', $this->prefix('@responder'))); $container->getDefinition('router')->addSetup('MouseOver\\Storage\\DI\\StorageExtension::prependTo($service, ?)', [$this->prefix('@storageRoutes')]); }
public function install(Nette\DI\ContainerBuilder $builder) { foreach ($this->listener as $class_name => $on) { $definition = $builder->getDefinition("annevents." . $class_name); foreach ($on as $on_name => $data) { foreach ($data['call'] as $add) { $definition->addSetup('$service->' . $on_name . '[]=?->' . $add['method'], array($builder->getDefinition('annevents.' . str_replace('\\', '_', $add['class'])))); } } } }
private function prepareNetteDatabase(\Nette\DI\ContainerBuilder $builder) { $ndbConnectionSectionKeys = ['dsn' => NULL, 'user' => NULL, 'password' => NULL]; /** @var \Nette\DI\CompilerExtension $extension */ foreach ($this->compiler->getExtensions('Nette\\Bridges\\DatabaseDI\\DatabaseExtension') as $extension) { if (array_intersect_key($extension->config, $ndbConnectionSectionKeys)) { $extensionConfig = $extension->config; $definitionName = $extension->name . '.default.connection'; $builder->getDefinition($definitionName)->setClass('Testbench\\Mocks\\NetteDatabaseConnectionMock', [$extensionConfig['dsn'], $extensionConfig['user'], $extensionConfig['password'], isset($extensionConfig['options']) ? $extensionConfig['options'] + ['lazy' => TRUE] : []]); } else { foreach ($extension->config as $sectionName => $sectionConfig) { $definitionName = $extension->name . '.' . $sectionName . '.connection'; $builder->getDefinition($definitionName)->setClass('Testbench\\Mocks\\NetteDatabaseConnectionMock', [$sectionConfig['dsn'], $sectionConfig['user'], $sectionConfig['password'], isset($sectionConfig['options']) ? $sectionConfig['options'] + ['lazy' => TRUE] : []]); } } } }
/** * @param string $serviceName * @param string $cacheDirectory */ private function createEagerProxy($serviceName, $cacheDirectory) { $definition = $this->builder->getDefinition($serviceName); $this->builder->removeDefinition($serviceName); $hiddenServiceName = $this->prefix($serviceName); $proxyClassName = $definition->getClass() . md5(serialize($definition)); $this->builder->addDefinition($serviceName)->setClass($proxyClassName)->setFactory('@' . $this->prefix('eagerServiceFactory') . '::create', array($hiddenServiceName, $proxyClassName)); $this->builder->addDefinition($hiddenServiceName, $definition)->setAutowired(false); if (!class_exists($proxyClassName)) { $classGenerator = new ClassGenerator(); $this->proxyGenerator->generate(new \ReflectionClass($definition->getClass()), $classGenerator); $classGenerator->setName($proxyClassName); $code = '<?php' . ClassGenerator::LINE_FEED . $classGenerator->generate(); $tempPath = $cacheDirectory . uniqid() . ".php"; $backslashPos = strrpos($proxyClassName, '\\'); $newPath = $cacheDirectory . substr($proxyClassName, $backslashPos ? $backslashPos + 1 : 0) . ".php"; file_put_contents($tempPath, $code, LOCK_EX); rename($tempPath, $newPath); require_once $newPath; } }
private function createSubscribersMap(\Nette\DI\ContainerBuilder $builder) { $map = []; foreach ($builder->findByTag(self::TAG_SUBSCRIBER) as $serviceName => $tagProperties) { $def = $builder->getDefinition($serviceName); $class = $def->getClass(); $events = $class::getSubscribedEvents(); foreach ($events as $eventName => $callbacks) { foreach ($callbacks as $function) { $map[$eventName][] = [$serviceName, $function]; } } } return $map; }
/** * @param ContainerBuilder $builder * @throws \movi\InvalidArgumentException */ private function processPackages(ContainerBuilder $builder) { $manager = $builder->getDefinition($this->prefix('manager')); $packages = $builder->parameters['packages']; if (count($packages) > 0) { foreach (array_values($packages) as $data) { $class = $this->getPackageClass($data); if (class_exists($class)) { $package = new $class($data); if (!$package instanceof Package) { throw new InvalidArgumentException("Package class must be an instance of movi\\Packages\\Package."); } } else { $package = new Package($data); } // Compile the package $package->onCompile($this->compiler); $this->processExtensions($package->extensions); $manager->addSetup('addPackage', [$package]); } } }
private function setupRouting(ContainerBuilder $container, array $config) { $router = $container->addDefinition('router')->setClass('Nette\\Application\\Routers\\RouteList'); foreach ($config['routes'] as $mask => $action) { $router->addSetup('$service[] = new Nette\\Application\\Routers\\Route(?, ?);', array($mask, $action)); } if ($container->parameters['debugMode'] && $config['debugger']) { $container->getDefinition('application')->addSetup('Nette\\Diagnostics\\Debugger::getBar()->addPanel(?)', array(new Nette\DI\Statement('Nette\\Application\\Diagnostics\\RoutingPanel'))); } }
static function parseServices(Nette\DI\ContainerBuilder $container, array $config) { $all = isset($config['services']) ? $config['services'] : array(); $all += isset($config['factories']) ? $config['factories'] : array(); uasort($all, function ($a, $b) { return strcmp(Config::isInheriting($a), Config::isInheriting($b)); }); foreach ($all as $name => $def) { if ($parent = Config::takeParent($def)) { $container->removeDefinition($name); $definition = $container->addDefinition($name); if ($parent !== Config::OVERWRITE) { foreach ($container->getDefinition($parent) as $k => $v) { $definition->{$k} = $v; } } } elseif ($container->hasDefinition($name)) { $definition = $container->getDefinition($name); } else { $definition = $container->addDefinition($name); } try { static::parseService($definition, $def, isset($config['services'][$name])); } catch (\Exception $e) { throw new Nette\DI\ServiceCreationException("Service '{$name}': " . $e->getMessage(), NULL, $e); } } }
/** * $mapping => ['NAMESPACE' => 'NAMESPACE\\*Module\\Presenters\\*Presenter'] * * @param ContainerBuilder $builder * @param array $mapping */ public function setPresenterMapping(ContainerBuilder $builder, array $mapping) { $builder->getDefinition($builder->getByType(IPresenterFactory::class))->addSetup('setMapping', [$mapping]); }
/** * Parses section 'services' from (unexpanded) configuration file. * @return void */ public static function parseServices(ContainerBuilder $builder, array $config, $namespace = NULL) { if (!empty($config['factories'])) { throw new Nette\DeprecatedException("Section 'factories' is deprecated, move definitions to section 'services' and append key 'autowired: no'."); } $services = isset($config['services']) ? $config['services'] : array(); $depths = array(); foreach ($services as $name => $def) { $path = array(); while (Config\Helpers::isInheriting($def)) { $path[] = $def; $def = isset($services[$def[Config\Helpers::EXTENDS_KEY]]) ? $services[$def[Config\Helpers::EXTENDS_KEY]] : array(); if (in_array($def, $path, TRUE)) { throw new ServiceCreationException("Circular reference detected for service '{$name}'."); } } $depths[$name] = count($path); } array_multisort($depths, $services); foreach ($services as $origName => $def) { if ((string) (int) $origName === (string) $origName) { $postfix = $def instanceof Statement && is_string($def->getEntity()) ? '.' . $def->getEntity() : (is_scalar($def) ? ".{$def}" : ''); $name = count($builder->getDefinitions()) + 1 . preg_replace('#\\W+#', '_', $postfix); } else { $name = ($namespace ? $namespace . '.' : '') . strtr($origName, '\\', '_'); } $params = $builder->parameters; if (is_array($def) && isset($def['parameters'])) { foreach ((array) $def['parameters'] as $k => $v) { $v = explode(' ', is_int($k) ? $v : $k); $params[end($v)] = $builder::literal('$' . end($v)); } } $def = Helpers::expand($def, $params); if (($parent = Config\Helpers::takeParent($def)) && $parent !== $name) { $builder->removeDefinition($name); $definition = $builder->addDefinition($name, $parent === Config\Helpers::OVERWRITE ? NULL : unserialize(serialize($builder->getDefinition($parent)))); } elseif ($builder->hasDefinition($name)) { $definition = $builder->getDefinition($name); } else { $definition = $builder->addDefinition($name); } try { static::parseService($definition, $def); } catch (\Exception $e) { throw new ServiceCreationException("Service '{$name}': " . $e->getMessage(), NULL, $e); } if ($definition->getClass() === 'self' || $definition->getFactory() && $definition->getFactory()->getEntity() === 'self') { throw new Nette\DeprecatedException("Replace service definition '{$origName}: self' with '- {$origName}'."); } } }
private function setupRouting(ContainerBuilder $container, array $config) { $this->validate($config, $this->defaults['routing'], 'nette.routing'); $router = $container->addDefinition('router') // no namespace for back compatibility ->setClass('Nette\Application\Routers\RouteList'); foreach ($config['routes'] as $mask => $action) { $router->addSetup('$service[] = new Nette\Application\Routers\Route(?, ?);', array($mask, $action)); } if ($container->parameters['debugMode'] && $config['debugger']) { $container->getDefinition('application')->addSetup('Tracy\Debugger::getBar()->addPanel(?)', array( new Nette\DI\Statement('Nette\Bridges\ApplicationTracy\RoutingPanel') )); } }
/** * Parses section 'services' from (unexpanded) configuration file. * @return void */ public static function parseServices(ContainerBuilder $builder, array $config, string $namespace = NULL) { $services = isset($config['services']) ? $config['services'] : []; $depths = []; foreach ($services as $name => $def) { $path = []; while (Config\Helpers::isInheriting($def)) { $path[] = $def; $def = isset($services[$def[Config\Helpers::EXTENDS_KEY]]) ? $services[$def[Config\Helpers::EXTENDS_KEY]] : []; if (in_array($def, $path, TRUE)) { throw new ServiceCreationException("Circular reference detected for service '{$name}'."); } } $depths[$name] = count($path); } array_multisort($depths, $services); foreach ($services as $name => $def) { if ((string) (int) $name === (string) $name) { $postfix = $def instanceof Statement && is_string($def->getEntity()) ? '.' . $def->getEntity() : (is_scalar($def) ? ".{$def}" : ''); $name = count($builder->getDefinitions()) + 1 . preg_replace('#\\W+#', '_', $postfix); } elseif ($namespace) { $name = $namespace . '.' . $name; } $params = $builder->parameters; if (is_array($def) && isset($def['parameters'])) { foreach ((array) $def['parameters'] as $k => $v) { $v = explode(' ', is_int($k) ? $v : $k); $params[end($v)] = $builder::literal('$' . end($v)); } } $def = Helpers::expand($def, $params); if (($parent = Config\Helpers::takeParent($def)) && $parent !== $name) { $builder->removeDefinition($name); $definition = $builder->addDefinition($name, $parent === Config\Helpers::OVERWRITE ? NULL : unserialize(serialize($builder->getDefinition($parent)))); } elseif ($builder->hasDefinition($name)) { $definition = $builder->getDefinition($name); } else { $definition = $builder->addDefinition($name); } try { static::parseService($definition, $def); } catch (\Exception $e) { throw new ServiceCreationException("Service '{$name}': " . $e->getMessage(), 0, $e); } } }
/** * Parses section 'services' from configuration file. * * @return void */ public static function parseServices(Nette\DI\ContainerBuilder $container, array $config, $namespace = null) { $services = isset($config['services']) ? $config['services'] : array(); $factories = isset($config['factories']) ? $config['factories'] : array(); if ($tmp = array_intersect_key($services, $factories)) { $tmp = implode("', '", array_keys($tmp)); throw new Nette\DI\ServiceCreationException("It is not allowed to use services and factories with the same names: '{$tmp}'."); } $all = $services + $factories; uasort($all, function ($a, $b) { return strcmp(Helpers::isInheriting($a), Helpers::isInheriting($b)); }); foreach ($all as $name => $def) { $shared = array_key_exists($name, $services); $name = ($namespace ? $namespace . '.' : '') . $name; if (($parent = Helpers::takeParent($def)) && $parent !== $name) { $container->removeDefinition($name); $definition = $container->addDefinition($name); if ($parent !== Helpers::OVERWRITE) { foreach ($container->getDefinition($parent) as $k => $v) { $definition->{$k} = unserialize(serialize($v)); // deep clone } } } elseif ($container->hasDefinition($name)) { $definition = $container->getDefinition($name); if ($definition->shared !== $shared) { throw new Nette\DI\ServiceCreationException("It is not allowed to use service and factory with the same name '{$name}'."); } } else { $definition = $container->addDefinition($name); } try { static::parseService($definition, $def, $shared); } catch (\Exception $e) { throw new Nette\DI\ServiceCreationException("Service '{$name}': " . $e->getMessage(), null, $e); } } }
/** * @param ContainerBuilder $container * @param array $config */ private function loadResourceRoutePanel(ContainerBuilder $container, $config) { $container->addDefinition($this->prefix('panel'))->setClass('Drahak\\Restful\\Diagnostics\\ResourceRouterPanel')->setArguments(array($config['security']['privateKey'], isset($config['security']['requestTimeKey']) ? $config['security']['requestTimeKey'] : 'timestamp'))->addSetup('Nette\\Diagnostics\\Debugger::getBar()->addPanel(?)', array('@self')); $container->getDefinition('application')->addSetup('$service->onStartup[] = ?', array(array($this->prefix('@panel'), 'getTab'))); }
private function registerWidgets(ContainerBuilder $builder) { $widgets = $builder->getDefinition($this->prefix('widgets')); foreach (array_keys($builder->findByTag(self::WIDGET_TAG)) as $widget) { $definition = $builder->getDefinition($widget); if (!isset($definition->tags['name'])) { throw new InvalidArgumentException('Missing name for widget ' . $widget); } $name = $definition->tags['name']; $widgets->addSetup('addWidget', [$name, '@' . $widget]); } }
/** * @param \Nette\DI\ContainerBuilder $container * @param array $config */ private function setupApplication(ContainerBuilder $container) { if ($container->hasDefinition('nette.presenterFactory')) { $container->getDefinition('nette.presenterFactory')->addSetup('setMapping', [['Lohini' => 'LohiniModule\\*\\*Presenter']]); } }
/** * @param \Nette\DI\ContainerBuilder $builder */ private function setupProxyAuthorizator(ContainerBuilder $builder) { if ($default = $builder->getByType('Nette\\Security\\IAuthorizator')) { $builder->getDefinition($default)->setAutowired(FALSE); $builder->getDefinition($this->prefix('proxy'))->addSetup('setAuthorizator', ['@' . $default]); } else { $builder->removeDefinition($this->prefix('proxy')); } }
/** * Parses section 'services' from (unexpanded) configuration file. * @return void */ public static function parseServices(ContainerBuilder $builder, array $config, $namespace = NULL) { $services = isset($config['services']) ? $config['services'] : array(); $factories = isset($config['factories']) ? $config['factories'] : array(); $all = array_merge($services, $factories); uasort($all, function ($a, $b) { return strcmp(Config\Helpers::isInheriting($a), Config\Helpers::isInheriting($b)); }); if (!empty($config['factories'])) { trigger_error("Section 'factories' is deprecated, move definitions to section 'services' and append key 'autowired: no'.", E_USER_DEPRECATED); } foreach ($all as $origName => $def) { if ((string) (int) $origName === (string) $origName) { $name = count($builder->getDefinitions()) . preg_replace('#\\W+#', '_', $def instanceof \stdClass ? ".{$def->value}" : (is_scalar($def) ? ".{$def}" : '')); } elseif (array_key_exists($origName, $services) && array_key_exists($origName, $factories)) { throw new ServiceCreationException("It is not allowed to use services and factories with the same name: '{$origName}'."); } else { $name = ($namespace ? $namespace . '.' : '') . strtr($origName, '\\', '_'); } $params = $builder->parameters; if (is_array($def) && isset($def['parameters'])) { foreach ((array) $def['parameters'] as $k => $v) { $v = explode(' ', is_int($k) ? $v : $k); $params[end($v)] = $builder::literal('$' . end($v)); } } $def = Helpers::expand($def, $params); if (($parent = Config\Helpers::takeParent($def)) && $parent !== $name) { $builder->removeDefinition($name); $definition = $builder->addDefinition($name, $parent === Config\Helpers::OVERWRITE ? NULL : unserialize(serialize($builder->getDefinition($parent)))); } elseif ($builder->hasDefinition($name)) { $definition = $builder->getDefinition($name); } else { $definition = $builder->addDefinition($name); } try { static::parseService($definition, $def); } catch (\Exception $e) { throw new ServiceCreationException("Service '{$name}': " . $e->getMessage(), NULL, $e); } if (array_key_exists($origName, $factories)) { $definition->setAutowired(FALSE); } if ($definition->class === 'self') { $definition->class = $origName; trigger_error("Replace service definition '{$origName}: self' with '- {$origName}'.", E_USER_DEPRECATED); } if ($definition->factory && $definition->factory->entity === 'self') { $definition->factory->entity = $origName; trigger_error("Replace service definition '{$origName}: self' with '- {$origName}'.", E_USER_DEPRECATED); } } }
/** * @param \Nette\DI\ContainerBuilder $builder */ private function optimizeListeners(Nette\DI\ContainerBuilder $builder) { $listeners = array(); foreach ($this->listeners as $serviceName => $eventNames) { foreach ($eventNames as $eventName) { list($namespace, $event) = Kdyby\Events\Event::parseName($eventName); $listeners[$eventName][] = $serviceName; if (!$namespace || !class_exists($namespace)) { continue; // it might not even be a "classname" event namespace } // find all subclasses and register the listener to all the classes dispatching them foreach ($builder->getDefinitions() as $def) { if (!($class = $def->getClass())) { continue; // ignore unresolved classes } if (is_subclass_of($class, $namespace)) { $listeners["{$class}::{$event}"][] = $serviceName; } } } } foreach ($listeners as $id => $subscribers) { $listeners[$id] = array_unique($subscribers); } $builder->getDefinition($this->prefix('manager'))->setClass('Kdyby\\Events\\LazyEventManager', array($listeners))->setup = $this->allowedManagerSetup; }
/** * Parses section 'services' from configuration file. * @return void */ public static function parseServices(Nette\DI\ContainerBuilder $container, array $config, $namespace = NULL) { $services = isset($config['services']) ? $config['services'] : array(); $factories = isset($config['factories']) ? $config['factories'] : array(); $all = array_merge($services, $factories); uasort($all, function ($a, $b) { return strcmp(Helpers::isInheriting($a), Helpers::isInheriting($b)); }); foreach ($all as $origName => $def) { $shared = array_key_exists($origName, $services); if ((string) (int) $origName === (string) $origName) { $name = (string) (count($container->getDefinitions()) + 1); } elseif ($shared && array_key_exists($origName, $factories)) { throw new Nette\DI\ServiceCreationException("It is not allowed to use services and factories with the same name: '{$origName}'."); } else { $name = ($namespace ? $namespace . '.' : '') . strtr($origName, '\\', '_'); } if (($parent = Helpers::takeParent($def)) && $parent !== $name) { $container->removeDefinition($name); $definition = $container->addDefinition($name); if ($parent !== Helpers::OVERWRITE) { foreach ($container->getDefinition($parent) as $k => $v) { $definition->{$k} = unserialize(serialize($v)); // deep clone } } } elseif ($container->hasDefinition($name)) { $definition = $container->getDefinition($name); if ($definition->shared !== $shared) { throw new Nette\DI\ServiceCreationException("It is not allowed to use service and factory with the same name '{$name}'."); } } else { $definition = $container->addDefinition($name); } try { static::parseService($definition, $def, $shared); } catch (\Exception $e) { throw new Nette\DI\ServiceCreationException("Service '{$name}': " . $e->getMessage(), NULL, $e); } } }
/** * @param ContainerBuilder $builder * @param string $type * @return \Nette\DI\ServiceDefinition * @throws ServiceNotFoundException */ private static function getDefinitionByTypeChecked(ContainerBuilder $builder, $type) { return $builder->getDefinition(self::getDefinitionNameByTypeChecked($builder, $type)); }