Namespaces

  • Nette
    • Application
      • Diagnostics
      • Responses
      • Routers
      • UI
    • Caching
      • Storages
    • ComponentModel
    • Config
    • Database
      • Diagnostics
      • Drivers
      • Reflection
      • Table
    • DI
    • Diagnostics
    • Forms
      • Controls
      • Rendering
    • Http
    • Iterators
    • Latte
      • Macros
    • Loaders
    • Localization
    • Mail
    • Reflection
    • Security
    • Templating
    • Utils
  • NetteModule
  • None
  • PHP

Classes

  • Container
  • ContainerBuilder
  • ServiceBuilder

Interfaces

  • IContainer
  • IServiceBuilder

Exceptions

  • AmbiguousServiceException
  • MissingServiceException
  • Overview
  • Namespace
  • Class
  • Tree
  1: <?php
  2: 
  3: /**
  4:  * This file is part of the Nette Framework (http://nette.org)
  5:  *
  6:  * Copyright (c) 2004, 2011 David Grudl (http://davidgrudl.com)
  7:  *
  8:  * For the full copyright and license information, please view
  9:  * the file license.txt that was distributed with this source code.
 10:  */
 11: 
 12: namespace Nette\DI;
 13: 
 14: use Nette;
 15: 
 16: 
 17: 
 18: /**
 19:  * Basic container builder.
 20:  *
 21:  * @author     David Grudl
 22:  */
 23: class ContainerBuilder extends Nette\Object
 24: {
 25: 
 26:     /**
 27:      * Adds new services from list of definitions. Expands %param% and @service values.
 28:      * Format:
 29:      *   serviceName => array(
 30:      *      class => 'ClassName' or factory => 'Factory::create'
 31:      *      arguments => array(...)
 32:      *      methods => array(
 33:      *         array(methodName, array(...))
 34:      *         ...
 35:      *      )
 36:      *      tags => array(...)
 37:      *      alias => 'Service'
 38:      *   )
 39:      */
 40:     public function addDefinitions(IContainer $container, array $definitions)
 41:     {
 42:         foreach ($definitions as $name => $definition) {
 43:             if (is_scalar($definition)) {
 44:                 if (substr($definition, 0, 1) === '@') {
 45:                     $definition = array('alias' => substr($definition, 1));
 46:                 } else {
 47:                     $definition = array('class' => $definition);
 48:                 }
 49:             }
 50: 
 51:             $arguments = isset($definition['arguments']) ? $definition['arguments'] : array();
 52:             $expander = function(&$val) use ($container) {
 53:                 if (substr($val, 0, 1) === '@') {
 54:                     $val = $container->getService(substr($val, 1));
 55:                 } elseif (is_string($val)) {
 56:                     $val = Nette\Utils\Strings::expand($val, $container->params);
 57:                 }
 58:             };
 59: 
 60:             if (isset($definition['class']) || isset($definition['factory'])) {
 61:                 if (isset($definition['class'])) {
 62:                     $class = $definition['class'];
 63:                 } else {
 64:                     $class = NULL;
 65:                     array_unshift($arguments, $definition['factory']);
 66:                 }
 67:                 $methods = isset($definition['methods']) ? $definition['methods'] : array();
 68:                 $factory = function($container) use ($class, $arguments, $methods, $expander) {
 69:                     array_walk_recursive($arguments, $expander);
 70:                     if ($class) {
 71:                         $class = Nette\Utils\Strings::expand($class, $container->params);
 72:                         if ($arguments) {
 73:                             $service = Nette\Reflection\ClassType::from($class)->newInstanceArgs($arguments);
 74:                         } else {
 75:                             $service = new $class;
 76:                         }
 77:                     } else {
 78:                         $factory = $arguments[0]; $arguments[0] = $container;
 79:                         $service = call_user_func_array($factory, $arguments);
 80:                     }
 81: 
 82:                     array_walk_recursive($methods, $expander);
 83:                     foreach ($methods as $method) {
 84:                         call_user_func_array(array($service, $method[0]), isset($method[1]) ? $method[1] : array());
 85:                     }
 86: 
 87:                     return $service;
 88:                 };
 89: 
 90:             } elseif (isset($definition['alias'])) {
 91:                 $factory = function($container) use ($definition) {
 92:                     return $container->getService($definition['alias']);
 93:                 };
 94:             } else {
 95:                 throw new Nette\InvalidStateException("The definition of service '$name' is missing factory method.");
 96:             }
 97: 
 98:             if (isset($definition['tags'])) {
 99:                 $tags = (array) $definition['tags'];
100:                 array_walk_recursive($tags, $expander);
101:             } else {
102:                 $tags = NULL;
103:             }
104:             $container->addService($name, $factory, $tags);
105:         }
106:     }
107: 
108: 
109: 
110:     public function generateCode(array $definitions)
111:     {
112:         $code = '';
113:         foreach ($definitions as $name => $definition) {
114:             $name = $this->varExport($name);
115:             if (is_scalar($definition)) {
116:                 if (substr($definition, 0, 1) === '@') {
117:                     $definition = array('alias' => substr($definition, 1));
118:                 } else {
119:                     $factory = $this->varExport($definition);
120:                     $code .= "\$container->addService($name, $factory);\n\n";
121:                     continue;
122:                 }
123:             }
124: 
125:             if (isset($definition['class']) || isset($definition['factory'])) {
126:                 $arguments = $this->argsExport(isset($definition['arguments']) ? $definition['arguments'] : array());
127:                 $factory = "function(\$container) {\n\t";
128:                 $factory .= isset($definition['class'])
129:                     ? '$class = ' . $this->argsExport(array($definition['class'])) . '; $service = new $class(' . $arguments . ");\n"
130:                     : "\$service = call_user_func(\n\t\t" . $this->argsExport(array($definition['factory']))
131:                         . ",\n\t\t\$container" . ($arguments ? ",\n\t\t$arguments" : '') . "\n\t);\n";
132: 
133:                 if (isset($definition['methods'])) {
134:                     foreach ($definition['methods'] as $method) {
135:                         $args = isset($method[1]) ? $this->argsExport($method[1]) : '';
136:                         $factory .= "\t\$service->$method[0]($args);\n";
137:                     }
138:                 }
139:                 $factory .= "\treturn \$service;\n}";
140: 
141:             } elseif (isset($definition['alias'])) {
142:                 $factory = $this->varExport($definition['alias']);
143:                 $factory = "function(\$container) {\n\treturn \$container->getService($factory);\n}";
144:             } else {
145:                 throw new Nette\InvalidStateException("The definition of service '$name' is missing factory method.");
146:             }
147: 
148:             $tags = isset($definition['tags']) ? $this->argsExport(array($definition['tags'])) : 'NULL';
149:             $code .= "\$container->addService($name, $factory, $tags);\n\n";
150:         }
151:         return $code;
152:     }
153: 
154: 
155: 
156:     private function argsExport($args)
157:     {
158:         $args = implode(', ', array_map(array($this, 'varExport'), $args));
159:         $args = preg_replace("#(?<!\\\)'@(\w+)'#", '\$container->getService(\'$1\')', $args);
160:         $args = preg_replace("#(?<!\\\)'%([\w-]+)%'#", '\$container->params[\'$1\']', $args);
161:         $args = preg_replace("#(?<!\\\)'(?:[^'\\\]|\\\.)*%(?:[^'\\\]|\\\.)*'#", 'Nette\Utils\Strings::expand($0, \$container->params)', $args);
162:         return $args;
163:     }
164: 
165: 
166: 
167:     private function varExport($arg)
168:     {
169:         return preg_replace('#\n *#', ' ', var_export($arg, TRUE));
170:     }
171: 
172: }
173: 
Nette Framework 2.0beta1 API API documentation generated by ApiGen 2.3.0