ACC SHELL

Path : /srv/www/vhosts/usoenergy/libs/Nette/DI/
File Upload :
Current File : /srv/www/vhosts/usoenergy/libs/Nette/DI/ContainerBuilder.php

<?php

/**
 * This file is part of the Nette Framework (http://nette.org)
 *
 * Copyright (c) 2004, 2011 David Grudl (http://davidgrudl.com)
 *
 * For the full copyright and license information, please view
 * the file license.txt that was distributed with this source code.
 */

namespace Nette\DI;

use Nette;



/**
 * Basic container builder.
 *
 * @author     David Grudl
 */
class ContainerBuilder extends Nette\Object
{

	/**
	 * Adds new services from list of definitions. Expands %param% and @service values.
	 * Format:
	 *   serviceName => array(
	 *      class => 'ClassName' or factory => 'Factory::create'
	 *      arguments => array(...)
	 *      methods => array(
	 *         array(methodName, array(...))
	 *         ...
	 *      )
	 *      tags => array(...)
	 *      alias => 'Service'
	 *   )
	 */
	public function addDefinitions(IContainer $container, array $definitions)
	{
		foreach ($definitions as $name => $definition) {
			if (is_scalar($definition)) {
				if (substr($definition, 0, 1) === '@') {
					$definition = array('alias' => substr($definition, 1));
				} else {
					$definition = array('class' => $definition);
				}
			}

			$arguments = isset($definition['arguments']) ? $definition['arguments'] : array();
			$expander = function(&$val) use ($container) {
				if (substr($val, 0, 1) === '@') {
					$val = $container->getService(substr($val, 1));
				} elseif (is_string($val)) {
					$val = Nette\Utils\Strings::expand($val, $container->params);
				}
			};

			if (isset($definition['class']) || isset($definition['factory'])) {
				if (isset($definition['class'])) {
					$class = $definition['class'];
				} else {
					$class = NULL;
					array_unshift($arguments, $definition['factory']);
				}
				$methods = isset($definition['methods']) ? $definition['methods'] : array();
				$factory = function($container) use ($class, $arguments, $methods, $expander) {
					array_walk_recursive($arguments, $expander);
					if ($class) {
						$class = Nette\Utils\Strings::expand($class, $container->params);
						if ($arguments) {
							$service = Nette\Reflection\ClassType::from($class)->newInstanceArgs($arguments);
						} else {
							$service = new $class;
						}
					} else {
						$factory = $arguments[0]; $arguments[0] = $container;
						$service = call_user_func_array($factory, $arguments);
					}

					array_walk_recursive($methods, $expander);
					foreach ($methods as $method) {
						call_user_func_array(array($service, $method[0]), isset($method[1]) ? $method[1] : array());
					}

					return $service;
				};

			} elseif (isset($definition['alias'])) {
				$factory = function($container) use ($definition) {
					return $container->getService($definition['alias']);
				};
			} else {
				throw new Nette\InvalidStateException("The definition of service '$name' is missing factory method.");
			}

			if (isset($definition['tags'])) {
				$tags = (array) $definition['tags'];
				array_walk_recursive($tags, $expander);
			} else {
				$tags = NULL;
			}
			$container->addService($name, $factory, $tags);
		}
	}



	public function generateCode(array $definitions)
	{
		$code = '';
		foreach ($definitions as $name => $definition) {
			$name = $this->varExport($name);
			if (is_scalar($definition)) {
				if (substr($definition, 0, 1) === '@') {
					$definition = array('alias' => substr($definition, 1));
				} else {
					$factory = $this->varExport($definition);
					$code .= "\$container->addService($name, $factory);\n\n";
					continue;
				}
			}

			if (isset($definition['class']) || isset($definition['factory'])) {
				$arguments = $this->argsExport(isset($definition['arguments']) ? $definition['arguments'] : array());
				$factory = "function(\$container) {\n\t";
				$factory .= isset($definition['class'])
					? '$class = ' . $this->argsExport(array($definition['class'])) . '; $service = new $class(' . $arguments . ");\n"
					: "\$service = call_user_func(\n\t\t" . $this->argsExport(array($definition['factory']))
						. ",\n\t\t\$container" . ($arguments ? ",\n\t\t$arguments" : '') . "\n\t);\n";

				if (isset($definition['methods'])) {
					foreach ($definition['methods'] as $method) {
						$args = isset($method[1]) ? $this->argsExport($method[1]) : '';
						$factory .= "\t\$service->$method[0]($args);\n";
					}
				}
				$factory .= "\treturn \$service;\n}";

			} elseif (isset($definition['alias'])) {
				$factory = $this->varExport($definition['alias']);
				$factory = "function(\$container) {\n\treturn \$container->getService($factory);\n}";
			} else {
				throw new Nette\InvalidStateException("The definition of service '$name' is missing factory method.");
			}

			$tags = isset($definition['tags']) ? $this->argsExport(array($definition['tags'])) : 'NULL';
			$code .= "\$container->addService($name, $factory, $tags);\n\n";
		}
		return $code;
	}



	private function argsExport($args)
	{
		$args = implode(', ', array_map(array($this, 'varExport'), $args));
		$args = preg_replace("#(?<!\\\)'@(\w+)'#", '\$container->getService(\'$1\')', $args);
		$args = preg_replace("#(?<!\\\)'%([\w-]+)%'#", '\$container->params[\'$1\']', $args);
		$args = preg_replace("#(?<!\\\)'(?:[^'\\\]|\\\.)*%(?:[^'\\\]|\\\.)*'#", 'Nette\Utils\Strings::expand($0, \$container->params)', $args);
		return $args;
	}



	private function varExport($arg)
	{
		return preg_replace('#\n *#', ' ', var_export($arg, TRUE));
	}

}

ACC SHELL 2018