File indexing completed on 2024-12-29 05:28:08
0001 <?php 0002 /** 0003 * Zend Framework 0004 * 0005 * LICENSE 0006 * 0007 * This source file is subject to the new BSD license that is bundled 0008 * with this package in the file LICENSE.txt. 0009 * It is also available through the world-wide-web at this URL: 0010 * http://framework.zend.com/license/new-bsd 0011 * If you did not receive a copy of the license and are unable to 0012 * obtain it through the world-wide-web, please send an email 0013 * to license@zend.com so we can send you a copy immediately. 0014 * 0015 * @category Zend 0016 * @package Zend_Tool 0017 * @subpackage Framework 0018 * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) 0019 * @license http://framework.zend.com/license/new-bsd New BSD License 0020 * @version $Id$ 0021 */ 0022 0023 /** 0024 * @see Zend_Reflection_Class 0025 */ 0026 // require_once 'Zend/Reflection/Class.php'; 0027 0028 /** 0029 * @see Zend_Tool_Framework_Registry 0030 */ 0031 // require_once 'Zend/Tool/Framework/Registry/EnabledInterface.php'; 0032 0033 /** 0034 * @see Zend_Tool_Framework_Action_Base 0035 */ 0036 // require_once 'Zend/Tool/Framework/Action/Base.php'; 0037 0038 /** 0039 * The purpose of Zend_Tool_Framework_Provider_Signature is to derive 0040 * callable signatures from the provided provider. 0041 * 0042 * @category Zend 0043 * @package Zend_Tool 0044 * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) 0045 * @license http://framework.zend.com/license/new-bsd New BSD License 0046 */ 0047 class Zend_Tool_Framework_Provider_Signature implements Zend_Tool_Framework_Registry_EnabledInterface 0048 { 0049 0050 /** 0051 * @var Zend_Tool_Framework_Registry 0052 */ 0053 protected $_registry = null; 0054 0055 /** 0056 * @var Zend_Tool_Framework_Provider_Interface 0057 */ 0058 protected $_provider = null; 0059 0060 /** 0061 * @var string 0062 */ 0063 protected $_name = null; 0064 0065 /** 0066 * @var array 0067 */ 0068 protected $_specialties = array(); 0069 0070 /** 0071 * @var array 0072 */ 0073 protected $_actionableMethods = array(); 0074 0075 /** 0076 * @var unknown_type 0077 */ 0078 protected $_actions = array(); 0079 0080 /** 0081 * @var Zend_Reflection_Class 0082 */ 0083 protected $_providerReflection = null; 0084 0085 /** 0086 * @var bool 0087 */ 0088 protected $_isProcessed = false; 0089 0090 /** 0091 * Constructor 0092 * 0093 * @param Zend_Tool_Framework_Provider_Interface $provider 0094 */ 0095 public function __construct(Zend_Tool_Framework_Provider_Interface $provider) 0096 { 0097 $this->_provider = $provider; 0098 $this->_providerReflection = new Zend_Reflection_Class($provider); 0099 } 0100 0101 /** 0102 * setRegistry() 0103 * 0104 * @param Zend_Tool_Framework_Registry_Interface $registry 0105 * @return Zend_Tool_Framework_Provider_Signature 0106 */ 0107 public function setRegistry(Zend_Tool_Framework_Registry_Interface $registry) 0108 { 0109 $this->_registry = $registry; 0110 return $this; 0111 } 0112 0113 public function process() 0114 { 0115 if ($this->_isProcessed) { 0116 return; 0117 } 0118 0119 $this->_process(); 0120 } 0121 0122 /** 0123 * getName() of the provider 0124 * 0125 * @return unknown 0126 */ 0127 public function getName() 0128 { 0129 return $this->_name; 0130 } 0131 0132 /** 0133 * Get the provider for this signature 0134 * 0135 * @return Zend_Tool_Framework_Provider_Interface 0136 */ 0137 public function getProvider() 0138 { 0139 return $this->_provider; 0140 } 0141 0142 /** 0143 * getProviderReflection() 0144 * 0145 * @return Zend_Reflection_Class 0146 */ 0147 public function getProviderReflection() 0148 { 0149 return $this->_providerReflection; 0150 } 0151 0152 /** 0153 * getSpecialities() 0154 * 0155 * @return array 0156 */ 0157 public function getSpecialties() 0158 { 0159 return $this->_specialties; 0160 } 0161 0162 /** 0163 * getActions() 0164 * 0165 * @return array Array of Actions 0166 */ 0167 public function getActions() 0168 { 0169 return $this->_actions; 0170 } 0171 0172 /** 0173 * getActionableMethods() 0174 * 0175 * @return array 0176 */ 0177 public function getActionableMethods() 0178 { 0179 return $this->_actionableMethods; 0180 } 0181 0182 /** 0183 * getActionableMethod() - Get an actionable method by name, this will return an array of 0184 * useful information about what can be exectued on this provider 0185 * 0186 * @param string $methodName 0187 * @return array 0188 */ 0189 public function getActionableMethod($methodName) 0190 { 0191 if (isset($this->_actionableMethods[$methodName])) { 0192 return $this->_actionableMethods[$methodName]; 0193 } 0194 0195 return false; 0196 } 0197 0198 /** 0199 * getActionableMethodByActionName() - Get an actionable method by its action name, this 0200 * will return an array of useful information about what can be exectued on this provider 0201 * 0202 * @param string $actionName 0203 * @return array 0204 */ 0205 public function getActionableMethodByActionName($actionName, $specialtyName = '_Global') 0206 { 0207 foreach ($this->_actionableMethods as $actionableMethod) { 0208 if ($actionName == $actionableMethod['actionName'] 0209 && $specialtyName == $actionableMethod['specialty']) { 0210 return $actionableMethod; 0211 } 0212 } 0213 0214 return false; 0215 } 0216 0217 /** 0218 * _process() is called at construction time and is what will build the signature information 0219 * for determining what is actionable 0220 * 0221 */ 0222 protected function _process() 0223 { 0224 $this->_isProcessed = true; 0225 $this->_processName(); 0226 $this->_processSpecialties(); 0227 $this->_processActionableMethods(); 0228 } 0229 0230 /** 0231 * _processName(); 0232 * 0233 */ 0234 protected function _processName() 0235 { 0236 if (method_exists($this->_provider, 'getName')) { 0237 $this->_name = $this->_provider->getName(); 0238 } 0239 0240 if ($this->_name == null) { 0241 $className = get_class($this->_provider); 0242 $name = $className; 0243 if (strpos($name, '_')) { 0244 $name = substr($name, strrpos($name, '_')+1); 0245 } 0246 $name = preg_replace('#(Provider|Manifest)$#', '', $name); 0247 $this->_name = $name; 0248 } 0249 } 0250 0251 /** 0252 * _processSpecialties() - Break out the specialty names for this provider 0253 * 0254 */ 0255 protected function _processSpecialties() 0256 { 0257 $specialties = array(); 0258 0259 if ($this->_providerReflection->hasMethod('getSpecialties')) { 0260 $specialties = $this->_provider->getSpecialties(); 0261 if (!is_array($specialties)) { 0262 // require_once 'Zend/Tool/Framework/Provider/Exception.php'; 0263 throw new Zend_Tool_Framework_Provider_Exception( 0264 'Provider ' . get_class($this->_provider) . ' must return an array for method getSpecialties().' 0265 ); 0266 } 0267 } else { 0268 $defaultProperties = $this->_providerReflection->getDefaultProperties(); 0269 $specialties = (isset($defaultProperties['_specialties'])) ? $defaultProperties['_specialties'] : array(); 0270 if (!is_array($specialties)) { 0271 // require_once 'Zend/Tool/Framework/Provider/Exception.php'; 0272 throw new Zend_Tool_Framework_Provider_Exception( 0273 'Provider ' . get_class($this->_provider) . '\'s property $_specialties must be an array.' 0274 ); 0275 } 0276 } 0277 0278 $this->_specialties = array_merge(array('_Global'), $specialties); 0279 0280 } 0281 0282 /** 0283 * _processActionableMethods() - process all methods that can be called on this provider. 0284 * 0285 */ 0286 protected function _processActionableMethods() 0287 { 0288 0289 $specialtyRegex = '#(.*)(' . implode('|', $this->_specialties) . ')$#i'; 0290 0291 0292 $methods = $this->_providerReflection->getMethods(); 0293 0294 $actionableMethods = array(); 0295 foreach ($methods as $method) { 0296 0297 $methodName = $method->getName(); 0298 0299 /** 0300 * the following will determine what methods are actually actionable 0301 * public, non-static, non-underscore prefixed, classes that dont 0302 * contain the name " 0303 */ 0304 if (!$method->getDeclaringClass()->isInstantiable() 0305 || !$method->isPublic() 0306 || $methodName[0] == '_' 0307 || $method->isStatic() 0308 || in_array($methodName, array('getContextClasses', 'getName')) // other protected public methods will nee to go here 0309 ) { 0310 continue; 0311 } 0312 0313 /** 0314 * check to see if the method was a required method by a Zend_Tool_* interface 0315 */ 0316 foreach ($method->getDeclaringClass()->getInterfaces() as $methodDeclaringClassInterface) { 0317 if (strpos($methodDeclaringClassInterface->getName(), 'Zend_Tool_') === 0 0318 && $methodDeclaringClassInterface->hasMethod($methodName)) { 0319 continue 2; 0320 } 0321 } 0322 0323 $actionableName = ucfirst($methodName); 0324 0325 if (substr($actionableName, -6) == 'Action') { 0326 $actionableName = substr($actionableName, 0, -6); 0327 } 0328 0329 $actionableMethods[$methodName]['methodName'] = $methodName; 0330 0331 $matches = null; 0332 if (preg_match($specialtyRegex, $actionableName, $matches)) { 0333 $actionableMethods[$methodName]['actionName'] = $matches[1]; 0334 $actionableMethods[$methodName]['specialty'] = $matches[2]; 0335 } else { 0336 $actionableMethods[$methodName]['actionName'] = $actionableName; 0337 $actionableMethods[$methodName]['specialty'] = '_Global'; 0338 } 0339 0340 // get the action, and create non-existent actions when they dont exist (the true part below) 0341 $action = $this->_registry->getActionRepository()->getAction($actionableMethods[$methodName]['actionName']); 0342 if ($action == null) { 0343 $action = new Zend_Tool_Framework_Action_Base($actionableMethods[$methodName]['actionName']); 0344 $this->_registry->getActionRepository()->addAction($action); 0345 } 0346 $actionableMethods[$methodName]['action'] = $action; 0347 0348 if (!in_array($actionableMethods[$methodName]['action'], $this->_actions)) { 0349 $this->_actions[] = $actionableMethods[$methodName]['action']; 0350 } 0351 0352 $parameterInfo = array(); 0353 $position = 1; 0354 foreach ($method->getParameters() as $parameter) { 0355 $currentParam = $parameter->getName(); 0356 $parameterInfo[$currentParam]['position'] = $position++; 0357 $parameterInfo[$currentParam]['optional'] = $parameter->isOptional(); 0358 $parameterInfo[$currentParam]['default'] = ($parameter->isOptional()) ? $parameter->getDefaultValue() : null; 0359 $parameterInfo[$currentParam]['name'] = $currentParam; 0360 $parameterInfo[$currentParam]['type'] = 'string'; 0361 $parameterInfo[$currentParam]['description'] = null; 0362 } 0363 0364 $matches = null; 0365 if (($docComment = $method->getDocComment()) != '' && 0366 (preg_match_all('/@param\s+(\w+)+\s+(\$\S+)\s+(.*?)(?=(?:\*\s*@)|(?:\*\/))/s', $docComment, $matches))) 0367 { 0368 for ($i=0; $i <= count($matches[0])-1; $i++) { 0369 $currentParam = ltrim($matches[2][$i], '$'); 0370 0371 if ($currentParam != '' && isset($parameterInfo[$currentParam])) { 0372 0373 $parameterInfo[$currentParam]['type'] = $matches[1][$i]; 0374 0375 $descriptionSource = $matches[3][$i]; 0376 0377 if ($descriptionSource != '') { 0378 $parameterInfo[$currentParam]['description'] = trim($descriptionSource); 0379 } 0380 0381 } 0382 0383 } 0384 0385 } 0386 0387 $actionableMethods[$methodName]['parameterInfo'] = $parameterInfo; 0388 0389 } 0390 0391 $this->_actionableMethods = $actionableMethods; 0392 } 0393 0394 }