7 * This source file is subject to the new BSD license that is bundled
8 * with this package in the file LICENSE.txt.
9 * It is also available through the world-wide-web at this URL:
10 * http://framework.zend.com/license/new-bsd
11 * If you did not receive a copy of the license and are unable to
12 * obtain it through the world-wide-web, please send an email
13 * to license@zend.com so we can send you a copy immediately.
17 * @subpackage Framework
18 * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
19 * @license http://framework.zend.com/license/new-bsd New BSD License
20 * @version $Id: Signature.php 16971 2009-07-22 18:05:45Z mikaelkael $
24 * @see Zend_Reflection_Class
26 require_once 'Zend/Reflection/Class.php';
29 * @see Zend_Tool_Framework_Registry
31 require_once 'Zend/Tool/Framework/Registry/EnabledInterface.php';
34 * @see Zend_Tool_Framework_Action_Base
36 require_once 'Zend/Tool/Framework/Action/Base.php';
39 * The purpose of Zend_Tool_Framework_Provider_Signature is to derive
40 * callable signatures from the provided provider.
44 * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
45 * @license http://framework.zend.com/license/new-bsd New BSD License
47 class Zend_Tool_Framework_Provider_Signature
implements Zend_Tool_Framework_Registry_EnabledInterface
51 * @var Zend_Tool_Framework_Registry
53 protected $_registry = null;
56 * @var Zend_Tool_Framework_Provider_Interface
58 protected $_provider = null;
63 protected $_name = null;
68 protected $_specialties = array();
73 protected $_actionableMethods = array();
78 protected $_actions = array();
81 * @var Zend_Reflection_Class
83 protected $_providerReflection = null;
88 protected $_isProcessed = false;
93 * @param Zend_Tool_Framework_Provider_Interface $provider
95 public function __construct(Zend_Tool_Framework_Provider_Interface
$provider)
97 $this->_provider
= $provider;
98 $this->_providerReflection
= new Zend_Reflection_Class($provider);
104 * @param Zend_Tool_Framework_Registry_Interface $registry
105 * @return Zend_Tool_Framework_Provider_Signature
107 public function setRegistry(Zend_Tool_Framework_Registry_Interface
$registry)
109 $this->_registry
= $registry;
113 public function process()
115 if ($this->_isProcessed
) {
123 * getName() of the provider
127 public function getName()
133 * Get the provider for this signature
135 * @return Zend_Tool_Framework_Provider_Interface
137 public function getProvider()
139 return $this->_provider
;
143 * getProviderReflection()
145 * @return Zend_Reflection_Class
147 public function getProviderReflection()
149 return $this->_providerReflection
;
157 public function getSpecialties()
159 return $this->_specialties
;
165 * @return array Array of Actions
167 public function getActions()
169 return $this->_actions
;
173 * getActionableMethods()
177 public function getActionableMethods()
179 return $this->_actionableMethods
;
183 * getActionableMethod() - Get an actionable method by name, this will return an array of
184 * useful information about what can be exectued on this provider
186 * @param string $methodName
189 public function getActionableMethod($methodName)
191 if (isset($this->_actionableMethods
[$methodName])) {
192 return $this->_actionableMethods
[$methodName];
199 * getActionableMethodByActionName() - Get an actionable method by its action name, this
200 * will return an array of useful information about what can be exectued on this provider
202 * @param string $actionName
205 public function getActionableMethodByActionName($actionName)
207 foreach ($this->_actionableMethods
as $actionableMethod) {
208 if ($actionName == $actionableMethod['actionName']) {
209 return $actionableMethod;
217 * _process() is called at construction time and is what will build the signature information
218 * for determining what is actionable
221 protected function _process()
223 $this->_isProcessed
= true;
224 $this->_processName();
225 $this->_processSpecialties();
226 $this->_processActionableMethods();
233 protected function _processName()
235 if (method_exists($this->_provider
, 'getName')) {
236 $this->_name
= $this->_provider
->getName();
239 if ($this->_name
== null) {
240 $className = get_class($this->_provider
);
241 $name = substr($className, strrpos($className, '_')+
1);
242 $name = preg_replace('#(Provider|Manifest)$#', '', $name);
243 $this->_name
= $name;
248 * _processSpecialties() - Break out the specialty names for this provider
251 protected function _processSpecialties()
253 $specialties = array();
255 if ($this->_providerReflection
->hasMethod('getSpecialties')) {
256 $specialties = $this->_provider
->getSpecialties();
257 if (!is_array($specialties)) {
258 require_once 'Zend/Tool/Framework/Provider/Exception.php';
259 throw new Zend_Tool_Framework_Provider_Exception(
260 'Provider ' . get_class($this->_provider
) . ' must return an array for method getSpecialties().'
264 $defaultProperties = $this->_providerReflection
->getDefaultProperties();
265 $specialties = (isset($defaultProperties['_specialties'])) ?
$defaultProperties['_specialties'] : array();
266 if (!is_array($specialties)) {
267 require_once 'Zend/Tool/Framework/Provider/Exception.php';
268 throw new Zend_Tool_Framework_Provider_Exception(
269 'Provider ' . get_class($this->_provider
) . '\'s property $_specialties must be an array.'
274 $this->_specialties
= array_merge(array('_Global'), $specialties);
279 * _processActionableMethods() - process all methods that can be called on this provider.
282 protected function _processActionableMethods()
285 $specialtyRegex = '#(.*)(' . implode('|', $this->_specialties
) . ')$#i';
288 $methods = $this->_providerReflection
->getMethods();
290 $actionableMethods = array();
291 foreach ($methods as $method) {
293 $methodName = $method->getName();
296 * the following will determine what methods are actually actionable
297 * public, non-static, non-underscore prefixed, classes that dont
300 if (!$method->getDeclaringClass()->isInstantiable()
301 ||
!$method->isPublic()
302 ||
$methodName[0] == '_'
303 ||
$method->isStatic()
304 ||
in_array($methodName, array('getContextClasses', 'getName')) // other protected public methods will nee to go here
310 * check to see if the method was a required method by a Zend_Tool_* interface
312 foreach ($method->getDeclaringClass()->getInterfaces() as $methodDeclaringClassInterface) {
313 if (strpos($methodDeclaringClassInterface->getName(), 'Zend_Tool_') === 0
314 && $methodDeclaringClassInterface->hasMethod($methodName)) {
319 $actionableName = ucfirst($methodName);
321 if (substr($actionableName, -6) == 'Action') {
322 $actionableName = substr($actionableName, 0, -6);
325 $actionableMethods[$methodName]['methodName'] = $methodName;
328 if (preg_match($specialtyRegex, $actionableName, $matches)) {
329 $actionableMethods[$methodName]['actionName'] = $matches[1];
330 $actionableMethods[$methodName]['specialty'] = $matches[2];
332 $actionableMethods[$methodName]['actionName'] = $actionableName;
333 $actionableMethods[$methodName]['specialty'] = '_Global';
336 // get the action, and create non-existent actions when they dont exist (the true part below)
337 $action = $this->_registry
->getActionRepository()->getAction($actionableMethods[$methodName]['actionName']);
338 if ($action == null) {
339 $action = new Zend_Tool_Framework_Action_Base($actionableMethods[$methodName]['actionName']);
340 $this->_registry
->getActionRepository()->addAction($action);
342 $actionableMethods[$methodName]['action'] = $action;
344 if (!in_array($actionableMethods[$methodName]['action'], $this->_actions
)) {
345 $this->_actions
[] = $actionableMethods[$methodName]['action'];
348 $parameterInfo = array();
350 foreach ($method->getParameters() as $parameter) {
351 $currentParam = $parameter->getName();
352 $parameterInfo[$currentParam]['position'] = $position++
;
353 $parameterInfo[$currentParam]['optional'] = $parameter->isOptional();
354 $parameterInfo[$currentParam]['default'] = ($parameter->isOptional()) ?
$parameter->getDefaultValue() : null;
355 $parameterInfo[$currentParam]['name'] = $currentParam;
356 $parameterInfo[$currentParam]['type'] = 'string';
357 $parameterInfo[$currentParam]['description'] = null;
361 if (($docComment = $method->getDocComment()) != '' &&
362 (preg_match_all('/@param\s+(\w+)+\s+(\$\S+)\s+(.*?)(?=(?:\*\s*@)|(?:\*\/))/s', $docComment, $matches)))
364 for ($i=0; $i <= count($matches[0])-1; $i++
) {
365 $currentParam = ltrim($matches[2][$i], '$');
367 if ($currentParam != '' && isset($parameterInfo[$currentParam])) {
369 $parameterInfo[$currentParam]['type'] = $matches[1][$i];
371 $descriptionSource = $matches[3][$i];
373 if ($descriptionSource != '') {
374 $parameterInfo[$currentParam]['description'] = trim($descriptionSource);
383 $actionableMethods[$methodName]['parameterInfo'] = $parameterInfo;
387 $this->_actionableMethods
= $actionableMethods;