source: trunk/www.guidonia.net/wp/wp-content/plugins/tubepress/classes/net/sourceforge/phpcrafty/ComponentFactory.class.php@ 44

Last change on this file since 44 was 44, checked in by luciano, 14 years ago
File size: 5.2 KB
Line 
1<?php
2
3function_exists('tubepress_load_classes')
4 || require(dirname(__FILE__) . '/../../../tubepress_classloader.php');
5tubepress_load_classes(array('net_sourceforge_phpcrafty_ComponentSpec',
6 'net_sourceforge_phpcrafty_ComponentReference',
7 'net_sourceforge_phpcrafty_ComponentReflector',
8 ));
9
10/**
11 * A factory class for the dependency injection container.
12 * Reads from specifications for components and creates configured instances
13 * based upon them.
14 * @author Chris Corbyn
15 * @package Crafty
16 */
17class net_sourceforge_phpcrafty_ComponentFactory
18{
19
20 /**
21 * ComponentSpec collection.
22 * @var net_sourceforge_phpcrafty_ComponentSpec[]
23 */
24 private $_specs = array();
25
26 /**
27 * Shared component instances
28 * @var mixed[]
29 */
30 private $_sharedInstances = array();
31
32 /**
33 * Creates a new instance of the ComponentSpec class.
34 * @return net_sourceforge_phpcrafty_ComponentSpec
35 */
36 public function newComponentSpec($className = null, $constructorArgs = array(),
37 $properties = array(), $shared = false)
38 {
39 return new net_sourceforge_phpcrafty_ComponentSpec($className, $constructorArgs, $properties,
40 $shared);
41 }
42
43 /**
44 * Creates a new ComponentReference for the given $componentName.
45 * @param string $componentName
46 * @return net_sourceforge_phpcrafty_ComponentReference
47 */
48 public function referenceFor($componentName)
49 {
50 return new net_sourceforge_phpcrafty_ComponentReference($componentName);
51 }
52
53 /**
54 * Create a new ComponentReflector for the given class with the given
55 * properties.
56 * @param string $className
57 * @param mixed[] $properties
58 * @return net_sourceforge_phpcrafty_ComponentReflector
59 * @access private
60 */
61 private function _newComponentReflector($className, $properties)
62 {
63 return new net_sourceforge_phpcrafty_ComponentReflector($className, $properties);
64 }
65
66 /**
67 * Sets the specification for the given $componentName.
68 * @param string $componentName
69 * @param net_sourceforge_phpcrafty_ComponentSpec The specification for $componentName
70 */
71 public function setComponentSpec($componentName, net_sourceforge_phpcrafty_ComponentSpec $spec)
72 {
73 $this->_specs[$componentName] = $spec;
74 }
75
76 /**
77 * Gets the specification for the given $componentName.
78 * @param string $componentName
79 * @return net_sourceforge_phpcrafty_ComponentSpec
80 * @throws net_sourceforge_phpcrafty_ComponenyFactoryException If spec is not found
81 */
82 public function getComponentSpec($componentName)
83 {
84 return $this->_specs[$componentName];
85 }
86
87
88 /**
89 * Test if the given parameter is a dependency to be resolved.
90 * @param mixed $input
91 * @return boolean
92 * @access private
93 */
94 private function _isDependency($input)
95 {
96 return ($input instanceof net_sourceforge_phpcrafty_ComponentReference);
97 }
98
99 /**
100 * Resolve all dependencies from ComponentReference objects into their
101 * appropriate instances.
102 * @param mixed $input
103 * @return mixed
104 * @access private
105 */
106 private function _resolveDependencies($input)
107 {
108 if (is_array($input))
109 {
110 $ret = array();
111 foreach ($input as $value)
112 {
113 $ret[] = $this->_resolveDependencies($value);
114 }
115 return $ret;
116 }
117 else
118 {
119 if ($this->_isDependency($input))
120 {
121 $componentName = $input->getComponentName();
122 return $this->create($componentName);
123 }
124 else
125 {
126 return $input;
127 }
128 }
129 }
130
131 /**
132 * Get a ReflectionClass decorated to provide setter-based injection
133 * components during instantiation.
134 * @param string $componentName
135 * @return net_sourceforge_phpcrafty_ComponentReflector
136 */
137 public function classOf($componentName)
138 {
139 $spec = $this->getComponentSpec($componentName);
140
141 $className = $spec->getClassName();
142
143
144 //Apply properties
145 $properties = array();
146
147 foreach ($spec->getProperties() as $key => $value)
148 {
149 $properties[$key] = $this->_resolveDependencies($value);
150 }
151
152 $class = $this->_newComponentReflector($className, $properties);
153
154 return $class;
155 }
156
157 /**
158 * Create an instance of the given component.
159 * @param string $componentName
160 * @param mixed[] $constructorArgs, optional
161 * @return object
162 */
163 public function create($componentName, $constructorArgs = null)
164 {
165 $spec = $this->getComponentSpec($componentName);
166
167 //If shared instances are used, try to return a registered instance
168 // if not, reference it now
169 if ($spec->isShared())
170 {
171 if (isset($this->_sharedInstances[$componentName]))
172 {
173 return $this->_sharedInstances[$componentName];
174 }
175 else
176 {
177 $o = null;
178 $this->_sharedInstances[$componentName] =& $o;
179 }
180 }
181
182 //Get the Reflector
183 $class = $this->classOf($componentName);
184
185 //Determine constructor params
186 if (!is_array($constructorArgs))
187 {
188 $injectedArgs = $this->_resolveDependencies(
189 $spec->getConstructorArgs());
190 }
191 else
192 {
193 $injectedArgs = $this->_resolveDependencies($constructorArgs);
194 }
195
196 $o = $class->newInstanceArgs($injectedArgs);
197
198 if ($o instanceof org_tubepress_ioc_ContainerAware) {
199 $o->setContainer($this);
200 }
201
202 return $o;
203 }
204
205}
Note: See TracBrowser for help on using the repository browser.