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