1: <?php
2: /**
3: * This is a binder that finds methods marked with @inject and calls them with
4: * their dependencies. It must be stacked on another binder that actually
5: * creates the instance.
6: *
7: * @author Bob Mckee <bmckee@bywires.com>
8: * @author James Pepin <james@jamespepin.com>
9: * @author Chuck Hagenbuch <chuck@horde.org>
10: * @category Horde
11: * @package Injector
12: */
13: class Horde_Injector_Binder_AnnotatedSetters implements Horde_Injector_Binder
14: {
15: /**
16: * @var Horde_Injector_Binder
17: */
18: private $_binder;
19:
20: /**
21: * @var Horde_Injector_DependencyFinder
22: */
23: private $_dependencyFinder;
24:
25: /**
26: * Constructor.
27: *
28: * @param Horde_Injector_Binder $binder TODO
29: * @param Horde_Injector_DependencyFinder $finder TODO
30: *
31: */
32: public function __construct(Horde_Injector_Binder $binder,
33: Horde_Injector_DependencyFinder $finder = null)
34: {
35: $this->_binder = $binder;
36: $this->_dependencyFinder = is_null($finder)
37: ? new Horde_Injector_DependencyFinder()
38: : $finder;
39: }
40:
41: /**
42: * TODO
43: *
44: * @param Horde_Injector_Binder $binder TODO
45: *
46: * @return boolean Equality.
47: */
48: public function equals(Horde_Injector_Binder $otherBinder)
49: {
50: return ($otherBinder instanceof Horde_Injector_Binder_AnnotatedSetters) &&
51: $this->getBinder()->equals($otherBinder->getBinder());
52: }
53:
54: /**
55: * TODO
56: *
57: * @return Horde_Injector_Binder TODO
58: */
59: public function getBinder()
60: {
61: return $this->_binder;
62: }
63:
64: /**
65: * TODO
66: */
67: public function create(Horde_Injector $injector)
68: {
69: $instance = $this->_binder->create($injector);
70:
71: $reflectionClass = new ReflectionClass(get_class($instance));
72: $setters = $this->_findAnnotatedSetters($reflectionClass);
73: $this->_callSetters($setters, $injector, $instance);
74:
75: return $instance;
76: }
77:
78: /**
79: * Find all public methods in $reflectionClass that are annotated with
80: * @inject.
81: *
82: * @param ReflectionClass $reflectionClass TODO
83: *
84: * @return array TODO
85: */
86: private function _findAnnotatedSetters(ReflectionClass $reflectionClass)
87: {
88: $setters = array();
89: foreach ($reflectionClass->getMethods(ReflectionMethod::IS_PUBLIC) as $reflectionMethod) {
90: if ($this->_isSetterMethod($reflectionMethod)) {
91: $setters[] = $reflectionMethod;
92: }
93: }
94:
95: return $setters;
96: }
97:
98: /**
99: * Is a method a setter method, by the criteria we define (has a doc
100: * comment that includes @inject).
101: *
102: * @param ReflectionMethod $reflectionMethod TODO
103: */
104: private function _isSetterMethod(ReflectionMethod $reflectionMethod)
105: {
106: $docBlock = $reflectionMethod->getDocComment();
107: if ($docBlock) {
108: if (strpos($docBlock, '@inject') !== false) {
109: return true;
110: }
111: }
112:
113: return false;
114: }
115:
116: /**
117: * Call each ReflectionMethod in the $setters array, filling in its
118: * dependencies with the $injector.
119: *
120: * @param array $setters Array of ReflectionMethods to call.
121: * @param Horde_Injector $injector The injector to get dependencies from.
122: * @param object $instance The object to call setters on.
123: */
124: private function _callSetters(array $setters, Horde_Injector $injector,
125: $instance)
126: {
127: foreach ($setters as $setterMethod) {
128: $setterMethod->invokeArgs(
129: $instance,
130: $this->_dependencyFinder->getMethodDependencies($injector, $setterMethod)
131: );
132: }
133: }
134:
135: }
136: