web/lib/Zend/Tool/Framework/Provider/Signature.php
changeset 64 162c1de6545a
parent 19 1c2f13fd785c
child 68 ecaf28ffe26e
equal deleted inserted replaced
63:5b37998e522e 64:162c1de6545a
       
     1 <?php
       
     2 /**
       
     3  * Zend Framework
       
     4  *
       
     5  * LICENSE
       
     6  *
       
     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.
       
    14  *
       
    15  * @category   Zend
       
    16  * @package    Zend_Tool
       
    17  * @subpackage Framework
       
    18  * @copyright  Copyright (c) 2005-2010 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 23202 2010-10-21 15:08:15Z ralph $
       
    21  */
       
    22 
       
    23 /**
       
    24  * @see Zend_Reflection_Class
       
    25  */
       
    26 require_once 'Zend/Reflection/Class.php';
       
    27 
       
    28 /**
       
    29  * @see Zend_Tool_Framework_Registry
       
    30  */
       
    31 require_once 'Zend/Tool/Framework/Registry/EnabledInterface.php';
       
    32 
       
    33 /**
       
    34  * @see Zend_Tool_Framework_Action_Base
       
    35  */
       
    36 require_once 'Zend/Tool/Framework/Action/Base.php';
       
    37 
       
    38 /**
       
    39  * The purpose of Zend_Tool_Framework_Provider_Signature is to derive
       
    40  * callable signatures from the provided provider.
       
    41  *
       
    42  * @category   Zend
       
    43  * @package    Zend_Tool
       
    44  * @copyright  Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
       
    45  * @license    http://framework.zend.com/license/new-bsd     New BSD License
       
    46  */
       
    47 class Zend_Tool_Framework_Provider_Signature implements Zend_Tool_Framework_Registry_EnabledInterface
       
    48 {
       
    49 
       
    50     /**
       
    51      * @var Zend_Tool_Framework_Registry
       
    52      */
       
    53     protected $_registry = null;
       
    54 
       
    55     /**
       
    56      * @var Zend_Tool_Framework_Provider_Interface
       
    57      */
       
    58     protected $_provider = null;
       
    59 
       
    60     /**
       
    61      * @var string
       
    62      */
       
    63     protected $_name = null;
       
    64 
       
    65     /**
       
    66      * @var array
       
    67      */
       
    68     protected $_specialties = array();
       
    69 
       
    70     /**
       
    71      * @var array
       
    72      */
       
    73     protected $_actionableMethods = array();
       
    74 
       
    75     /**
       
    76      * @var unknown_type
       
    77      */
       
    78     protected $_actions = array();
       
    79 
       
    80     /**
       
    81      * @var Zend_Reflection_Class
       
    82      */
       
    83     protected $_providerReflection = null;
       
    84 
       
    85     /**
       
    86      * @var bool
       
    87      */
       
    88     protected $_isProcessed = false;
       
    89 
       
    90     /**
       
    91      * Constructor
       
    92      *
       
    93      * @param Zend_Tool_Framework_Provider_Interface $provider
       
    94      */
       
    95     public function __construct(Zend_Tool_Framework_Provider_Interface $provider)
       
    96     {
       
    97         $this->_provider = $provider;
       
    98         $this->_providerReflection = new Zend_Reflection_Class($provider);
       
    99     }
       
   100 
       
   101     /**
       
   102      * setRegistry()
       
   103      *
       
   104      * @param Zend_Tool_Framework_Registry_Interface $registry
       
   105      * @return Zend_Tool_Framework_Provider_Signature
       
   106      */
       
   107     public function setRegistry(Zend_Tool_Framework_Registry_Interface $registry)
       
   108     {
       
   109         $this->_registry = $registry;
       
   110         return $this;
       
   111     }
       
   112 
       
   113     public function process()
       
   114     {
       
   115         if ($this->_isProcessed) {
       
   116             return;
       
   117         }
       
   118 
       
   119         $this->_process();
       
   120     }
       
   121 
       
   122     /**
       
   123      * getName() of the provider
       
   124      *
       
   125      * @return unknown
       
   126      */
       
   127     public function getName()
       
   128     {
       
   129         return $this->_name;
       
   130     }
       
   131 
       
   132     /**
       
   133      * Get the provider for this signature
       
   134      *
       
   135      * @return Zend_Tool_Framework_Provider_Interface
       
   136      */
       
   137     public function getProvider()
       
   138     {
       
   139         return $this->_provider;
       
   140     }
       
   141 
       
   142     /**
       
   143      * getProviderReflection()
       
   144      *
       
   145      * @return Zend_Reflection_Class
       
   146      */
       
   147     public function getProviderReflection()
       
   148     {
       
   149         return $this->_providerReflection;
       
   150     }
       
   151 
       
   152     /**
       
   153      * getSpecialities()
       
   154      *
       
   155      * @return array
       
   156      */
       
   157     public function getSpecialties()
       
   158     {
       
   159         return $this->_specialties;
       
   160     }
       
   161 
       
   162     /**
       
   163      * getActions()
       
   164      *
       
   165      * @return array Array of Actions
       
   166      */
       
   167     public function getActions()
       
   168     {
       
   169         return $this->_actions;
       
   170     }
       
   171 
       
   172     /**
       
   173      * getActionableMethods()
       
   174      *
       
   175      * @return array
       
   176      */
       
   177     public function getActionableMethods()
       
   178     {
       
   179         return $this->_actionableMethods;
       
   180     }
       
   181 
       
   182     /**
       
   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
       
   185      *
       
   186      * @param string $methodName
       
   187      * @return array
       
   188      */
       
   189     public function getActionableMethod($methodName)
       
   190     {
       
   191         if (isset($this->_actionableMethods[$methodName])) {
       
   192             return $this->_actionableMethods[$methodName];
       
   193         }
       
   194 
       
   195         return false;
       
   196     }
       
   197 
       
   198     /**
       
   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
       
   201      *
       
   202      * @param string $actionName
       
   203      * @return array
       
   204      */
       
   205     public function getActionableMethodByActionName($actionName, $specialtyName = '_Global')
       
   206     {
       
   207         foreach ($this->_actionableMethods as $actionableMethod) {
       
   208             if ($actionName == $actionableMethod['actionName']
       
   209                 && $specialtyName == $actionableMethod['specialty']) {
       
   210                 return $actionableMethod;
       
   211             }
       
   212         }
       
   213 
       
   214         return false;
       
   215     }
       
   216 
       
   217     /**
       
   218      * _process() is called at construction time and is what will build the signature information
       
   219      * for determining what is actionable
       
   220      *
       
   221      */
       
   222     protected function _process()
       
   223     {
       
   224         $this->_isProcessed = true;
       
   225         $this->_processName();
       
   226         $this->_processSpecialties();
       
   227         $this->_processActionableMethods();
       
   228     }
       
   229 
       
   230     /**
       
   231      * _processName();
       
   232      *
       
   233      */
       
   234     protected function _processName()
       
   235     {
       
   236         if (method_exists($this->_provider, 'getName')) {
       
   237             $this->_name = $this->_provider->getName();
       
   238         }
       
   239 
       
   240         if ($this->_name == null) {
       
   241             $className = get_class($this->_provider);
       
   242             $name = $className;
       
   243             if (strpos($name, '_')) {
       
   244                 $name = substr($name, strrpos($name, '_')+1);
       
   245             }
       
   246             $name = preg_replace('#(Provider|Manifest)$#', '', $name);
       
   247             $this->_name = $name;
       
   248         }
       
   249     }
       
   250 
       
   251     /**
       
   252      * _processSpecialties() - Break out the specialty names for this provider
       
   253      *
       
   254      */
       
   255     protected function _processSpecialties()
       
   256     {
       
   257         $specialties = array();
       
   258 
       
   259         if ($this->_providerReflection->hasMethod('getSpecialties')) {
       
   260             $specialties = $this->_provider->getSpecialties();
       
   261             if (!is_array($specialties)) {
       
   262                 require_once 'Zend/Tool/Framework/Provider/Exception.php';
       
   263                 throw new Zend_Tool_Framework_Provider_Exception(
       
   264                     'Provider ' . get_class($this->_provider) . ' must return an array for method getSpecialties().'
       
   265                     );
       
   266             }
       
   267         } else {
       
   268             $defaultProperties = $this->_providerReflection->getDefaultProperties();
       
   269             $specialties = (isset($defaultProperties['_specialties'])) ? $defaultProperties['_specialties'] : array();
       
   270             if (!is_array($specialties)) {
       
   271                 require_once 'Zend/Tool/Framework/Provider/Exception.php';
       
   272                 throw new Zend_Tool_Framework_Provider_Exception(
       
   273                     'Provider ' . get_class($this->_provider) . '\'s property $_specialties must be an array.'
       
   274                     );
       
   275             }
       
   276         }
       
   277 
       
   278         $this->_specialties = array_merge(array('_Global'), $specialties);
       
   279 
       
   280     }
       
   281 
       
   282     /**
       
   283      * _processActionableMethods() - process all methods that can be called on this provider.
       
   284      *
       
   285      */
       
   286     protected function _processActionableMethods()
       
   287     {
       
   288 
       
   289         $specialtyRegex = '#(.*)(' . implode('|', $this->_specialties) . ')$#i';
       
   290 
       
   291 
       
   292         $methods = $this->_providerReflection->getMethods();
       
   293 
       
   294         $actionableMethods = array();
       
   295         foreach ($methods as $method) {
       
   296 
       
   297             $methodName = $method->getName();
       
   298 
       
   299             /**
       
   300              * the following will determine what methods are actually actionable
       
   301              * public, non-static, non-underscore prefixed, classes that dont
       
   302              * contain the name "
       
   303              */
       
   304             if (!$method->getDeclaringClass()->isInstantiable()
       
   305                 || !$method->isPublic()
       
   306                 || $methodName[0] == '_'
       
   307                 || $method->isStatic()
       
   308                 || in_array($methodName, array('getContextClasses', 'getName')) // other protected public methods will nee to go here
       
   309                 ) {
       
   310                 continue;
       
   311             }
       
   312 
       
   313             /**
       
   314              * check to see if the method was a required method by a Zend_Tool_* interface
       
   315              */
       
   316             foreach ($method->getDeclaringClass()->getInterfaces() as $methodDeclaringClassInterface) {
       
   317                 if (strpos($methodDeclaringClassInterface->getName(), 'Zend_Tool_') === 0
       
   318                     && $methodDeclaringClassInterface->hasMethod($methodName)) {
       
   319                     continue 2;
       
   320                 }
       
   321             }
       
   322 
       
   323             $actionableName = ucfirst($methodName);
       
   324 
       
   325             if (substr($actionableName, -6) == 'Action') {
       
   326                 $actionableName = substr($actionableName, 0, -6);
       
   327             }
       
   328 
       
   329             $actionableMethods[$methodName]['methodName'] = $methodName;
       
   330 
       
   331             $matches = null;
       
   332             if (preg_match($specialtyRegex, $actionableName, $matches)) {
       
   333                 $actionableMethods[$methodName]['actionName'] = $matches[1];
       
   334                 $actionableMethods[$methodName]['specialty'] = $matches[2];
       
   335             } else {
       
   336                 $actionableMethods[$methodName]['actionName'] = $actionableName;
       
   337                 $actionableMethods[$methodName]['specialty'] = '_Global';
       
   338             }
       
   339 
       
   340             // get the action, and create non-existent actions when they dont exist (the true part below)
       
   341             $action = $this->_registry->getActionRepository()->getAction($actionableMethods[$methodName]['actionName']);
       
   342             if ($action == null) {
       
   343                 $action = new Zend_Tool_Framework_Action_Base($actionableMethods[$methodName]['actionName']);
       
   344                 $this->_registry->getActionRepository()->addAction($action);
       
   345             }
       
   346             $actionableMethods[$methodName]['action'] = $action;
       
   347 
       
   348             if (!in_array($actionableMethods[$methodName]['action'], $this->_actions)) {
       
   349                 $this->_actions[] = $actionableMethods[$methodName]['action'];
       
   350             }
       
   351 
       
   352             $parameterInfo = array();
       
   353             $position = 1;
       
   354             foreach ($method->getParameters() as $parameter) {
       
   355                 $currentParam = $parameter->getName();
       
   356                 $parameterInfo[$currentParam]['position']    = $position++;
       
   357                 $parameterInfo[$currentParam]['optional']    = $parameter->isOptional();
       
   358                 $parameterInfo[$currentParam]['default']     = ($parameter->isOptional()) ? $parameter->getDefaultValue() : null;
       
   359                 $parameterInfo[$currentParam]['name']        = $currentParam;
       
   360                 $parameterInfo[$currentParam]['type']        = 'string';
       
   361                 $parameterInfo[$currentParam]['description'] = null;
       
   362             }
       
   363 
       
   364             $matches = null;
       
   365             if (($docComment = $method->getDocComment()) != '' &&
       
   366                 (preg_match_all('/@param\s+(\w+)+\s+(\$\S+)\s+(.*?)(?=(?:\*\s*@)|(?:\*\/))/s', $docComment, $matches)))
       
   367             {
       
   368                 for ($i=0; $i <= count($matches[0])-1; $i++) {
       
   369                     $currentParam = ltrim($matches[2][$i], '$');
       
   370 
       
   371                     if ($currentParam != '' && isset($parameterInfo[$currentParam])) {
       
   372 
       
   373                         $parameterInfo[$currentParam]['type'] = $matches[1][$i];
       
   374 
       
   375                         $descriptionSource = $matches[3][$i];
       
   376 
       
   377                         if ($descriptionSource != '') {
       
   378                             $parameterInfo[$currentParam]['description'] = trim($descriptionSource);
       
   379                         }
       
   380 
       
   381                     }
       
   382 
       
   383                 }
       
   384 
       
   385             }
       
   386 
       
   387             $actionableMethods[$methodName]['parameterInfo'] = $parameterInfo;
       
   388 
       
   389         }
       
   390 
       
   391         $this->_actionableMethods = $actionableMethods;
       
   392     }
       
   393 
       
   394 }