ACC SHELL

Path : /srv/www/vhosts/usoenergy/libs/Nette/DI/
File Upload :
Current File : /srv/www/vhosts/usoenergy/libs/Nette/DI/Container.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;



/**
 * The dependency injection container default implementation.
 *
 * @author     David Grudl
 */
class Container extends Nette\FreezableObject implements IContainer
{
	const TAG_TYPEHINT = 'typeHint';

	/** @var array  user parameters */
	public $params = array();

	/** @var array  storage for shared objects */
	private $registry = array();

	/** @var array  storage for service factories */
	private $factories = array();

	/** @var array  */
	private $tags = array();

	/** @var array circular reference detector */
	private $creating;



	/**
	 * Adds the specified service or service factory to the container.
	 * @param  string
	 * @param  mixed   object, class name or callback
	 * @param  mixed   array of tags or string typeHint
	 * @return Container|ServiceBuilder  provides a fluent interface
	 */
	public function addService($name, $service, $tags = NULL)
	{
		$this->updating();
		if (!is_string($name) || $name === '') {
			throw new Nette\InvalidArgumentException("Service name must be a non-empty string, " . gettype($name) . " given.");
		}

		if (isset($this->registry[$name]) || method_exists($this, "createService$name")) {
			throw new Nette\InvalidStateException("Service '$name' has already been registered.");
		}

		if (is_string($tags)) {
			$tags = array(self::TAG_TYPEHINT => array($tags));
		} elseif (is_array($tags)) {
			foreach ($tags as $id => $attrs) {
				if (is_int($id) && is_string($attrs)) {
					$tags[$attrs] = array();
					unset($tags[$id]);
				} elseif (!is_array($attrs)) {
					$tags[$id] = (array) $attrs;
				}
			}
		}

		if (is_string($service) && strpos($service, ':') === FALSE) { // class name
			if (!isset($tags[self::TAG_TYPEHINT][0])) {
				$tags[self::TAG_TYPEHINT][0] = $service;
			}
			$service = new ServiceBuilder($service);
		}

		if ($service instanceof IServiceBuilder) {
			$factory = array($service, 'createService');

		} elseif (is_object($service) && !$service instanceof \Closure && !$service instanceof Nette\Callback) {
			$this->registry[$name] = $service;
			$this->tags[$name] = $tags;
			return $this;

		} else {
			$factory = $service;
		}

		$this->factories[$name] = array(callback($factory));
		$this->tags[$name] = $tags;
		$this->registry[$name] = & $this->factories[$name][1]; // forces cloning using reference
		return $service;
	}



	/**
	 * Removes the specified service type from the container.
	 * @return void
	 */
	public function removeService($name)
	{
		$this->updating();
		unset($this->registry[$name], $this->factories[$name]);
	}



	/**
	 * Gets the service object by name.
	 * @param  string
	 * @return object
	 */
	public function getService($name)
	{
		if (isset($this->registry[$name])) {
			return $this->registry[$name];

		} elseif (isset($this->creating[$name])) {
			throw new Nette\InvalidStateException("Circular reference detected for services: "
				. implode(', ', array_keys($this->creating)) . ".");
		}

		if (isset($this->factories[$name])) {
			list($factory) = $this->factories[$name];
			if (!$factory->isCallable()) {
				throw new Nette\InvalidStateException("Unable to create service '$name', factory '$factory' is not callable.");
			}

			$this->creating[$name] = TRUE;
			try {
				$service = $factory($this);
			} catch (\Exception $e) {}

		} elseif (method_exists($this, $factory = 'createService' . ucfirst($name))) { // static method
			$this->creating[$name] = TRUE;
			try {
				$service = $this->$factory();
			} catch (\Exception $e) {}

		} else {
			throw new MissingServiceException("Service '$name' not found.");
		}

		unset($this->creating[$name]);

		if (isset($e)) {
			throw $e;

		} elseif (!is_object($service)) {
			throw new Nette\UnexpectedValueException("Unable to create service '$name', value returned by factory '$factory' is not object.");

		} elseif (isset($this->tags[$name][self::TAG_TYPEHINT][0]) && !$service instanceof $this->tags[$name][self::TAG_TYPEHINT][0]) {
			throw new Nette\UnexpectedValueException("Unable to create service '$name', value returned by factory '$factory' is not '{$this->tags[$name][self::TAG_TYPEHINT][0]}' type.");
		}

		unset($this->factories[$name]);
		return $this->registry[$name] = $service;
	}



	/**
	 * Gets the service object of the specified type.
	 * @param  string
	 * @return object
	 */
	public function getServiceByType($type)
	{
		foreach ($this->registry as $name => $service) {
			if (isset($this->tags[$name][self::TAG_TYPEHINT][0]) ? !strcasecmp($this->tags[$name][self::TAG_TYPEHINT][0], $type) : $service instanceof $type) {
				$found[] = $name;
			}
		}
		if (!isset($found)) {
			throw new MissingServiceException("Service matching '$type' type not found.");

		} elseif (count($found) > 1) {
			throw new AmbiguousServiceException("Found more than one service ('" . implode("', '", $found) . "') matching '$type' type.");
		}
		return $this->getService($found[0]);
	}



	/**
	 * Gets the service objects of the specified tag.
	 * @param  string
	 * @return array of [service name => tag attributes]
	 */
	public function getServiceNamesByTag($tag)
	{
		$found = array();
		foreach ($this->registry as $name => $service) {
			if (isset($this->tags[$name][$tag])) {
				$found[$name] = $this->tags[$name][$tag];
			}
		}
		return $found;
	}



	/**
	 * Does the service exist?
	 * @param  string service name
	 * @return bool
	 */
	public function hasService($name)
	{
		return isset($this->registry[$name])
			|| isset($this->factories[$name])
			|| method_exists($this, "createService$name");
	}



	/**
	 * Checks the service type.
	 * @param  string
	 * @param  string
	 * @return bool
	 */
	public function checkServiceType($name, $type)
	{
		return isset($this->tags[$name][self::TAG_TYPEHINT][0])
			? !strcasecmp($this->tags[$name][self::TAG_TYPEHINT][0], $type)
			: (isset($this->registry[$name]) && $this->registry[$name] instanceof $type);
	}



	/********************* shortcuts ****************d*g**/



	/**
	 * Expands %placeholders% in string.
	 * @param  mixed
	 * @return mixed
	 */
	public function expand($s)
	{
		return is_string($s) ? Nette\Utils\Strings::expand($s, $this->params) : $s;
	}



	/**
	 * Gets the service object, shortcut for getService().
	 * @param  string
	 * @return object
	 */
	public function &__get($name)
	{
		if (!isset($this->registry[$name])) {
			$this->getService($name);
		}
		return $this->registry[$name];
	}



	/**
	 * Adds the service object.
	 * @param  string
	 * @param  object
	 * @return void
	 */
	public function __set($name, $service)
	{
		$this->updating();
		if (!is_string($name) || $name === '') {
			throw new Nette\InvalidArgumentException("Service name must be a non-empty string, " . gettype($name) . " given.");

		} elseif (isset($this->registry[$name]) || method_exists($this, "createService$name")) {
			throw new Nette\InvalidStateException("Service '$name' has already been registered.");

		} elseif (!is_object($service)) {
			throw new Nette\InvalidArgumentException("Service must be a object, " . gettype($service) . " given.");
		}
		$this->registry[$name] = $service;
	}



	/**
	 * Does the service exist?
	 * @param  string
	 * @return bool
	 */
	public function __isset($name)
	{
		return $this->hasService($name);
	}



	/**
	 * Removes the service, shortcut for removeService().
	 * @return void
	 */
	public function __unset($name)
	{
		$this->removeService($name);
	}

}

ACC SHELL 2018