"Fossies" - the Fresh Open Source Software Archive

Member "icingaweb2-2.11.4/library/vendor/Zend/Server/Reflection/Function/Abstract.php" (26 Jan 2023, 15495 Bytes) of package /linux/www/icingaweb2-2.11.4.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) PHP source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file.

    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_Server
   17  * @copyright  Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
   18  * @license    http://framework.zend.com/license/new-bsd     New BSD License
   19  */
   20 
   21 /**
   22  * Zend_Server_Reflection_Node
   23  */
   24 
   25 /**
   26  * Zend_Server_Reflection_Parameter
   27  */
   28 
   29 /**
   30  * Zend_Server_Reflection_Prototype
   31  */
   32 
   33 /**
   34  * Function/Method Reflection
   35  *
   36  * Decorates a ReflectionFunction. Allows setting and retrieving an alternate
   37  * 'service' name (i.e., the name to be used when calling via a service),
   38  * setting and retrieving the description (originally set using the docblock
   39  * contents), retrieving the callback and callback type, retrieving additional
   40  * method invocation arguments, and retrieving the
   41  * method {@link Zend_Server_Reflection_Prototype prototypes}.
   42  *
   43  * @category   Zend
   44  * @package    Zend_Server
   45  * @subpackage Reflection
   46  * @copyright  Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
   47  * @license    http://framework.zend.com/license/new-bsd     New BSD License
   48  * @version $Id$
   49  */
   50 abstract class Zend_Server_Reflection_Function_Abstract
   51 {
   52     /**
   53      * @var ReflectionFunction
   54      */
   55     protected $_reflection;
   56 
   57     /**
   58      * Additional arguments to pass to method on invocation
   59      * @var array
   60      */
   61     protected $_argv = array();
   62 
   63     /**
   64      * Used to store extra configuration for the method (typically done by the
   65      * server class, e.g., to indicate whether or not to instantiate a class).
   66      * Associative array; access is as properties via {@link __get()} and
   67      * {@link __set()}
   68      * @var array
   69      */
   70     protected $_config = array();
   71 
   72     /**
   73      * Declaring class (needed for when serialization occurs)
   74      * @var string
   75      */
   76     protected $_class;
   77 
   78     /**
   79      * Function/method description
   80      * @var string
   81      */
   82     protected $_description = '';
   83 
   84     /**
   85      * Namespace with which to prefix function/method name
   86      * @var string
   87      */
   88     protected $_namespace;
   89 
   90     /**
   91      * Prototypes
   92      * @var array
   93      */
   94     protected $_prototypes = array();
   95 
   96     private $_return;
   97     private $_returnDesc;
   98     private $_paramDesc;
   99     private $_sigParams;
  100     private $_sigParamsDepth;
  101 
  102     /**
  103      * Constructor
  104      *
  105      * @param ReflectionFunction $r
  106      */
  107     public function __construct(Reflector $r, $namespace = null, $argv = array())
  108     {
  109         // In PHP 5.1.x, ReflectionMethod extends ReflectionFunction. In 5.2.x,
  110         // both extend ReflectionFunctionAbstract. So, we can't do normal type
  111         // hinting in the prototype, but instead need to do some explicit
  112         // testing here.
  113         if ((!$r instanceof ReflectionFunction)
  114             && (!$r instanceof ReflectionMethod)) {
  115             throw new Zend_Server_Reflection_Exception('Invalid reflection class');
  116         }
  117         $this->_reflection = $r;
  118 
  119         // Determine namespace
  120         if (null !== $namespace){
  121             $this->setNamespace($namespace);
  122         }
  123 
  124         // Determine arguments
  125         if (is_array($argv)) {
  126             $this->_argv = $argv;
  127         }
  128 
  129         // If method call, need to store some info on the class
  130         if ($r instanceof ReflectionMethod) {
  131             $this->_class = $r->getDeclaringClass()->getName();
  132         }
  133 
  134         // Perform some introspection
  135         $this->_reflect();
  136     }
  137 
  138     /**
  139      * Create signature node tree
  140      *
  141      * Recursive method to build the signature node tree. Increments through
  142      * each array in {@link $_sigParams}, adding every value of the next level
  143      * to the current value (unless the current value is null).
  144      *
  145      * @param Zend_Server_Reflection_Node $parent
  146      * @param int $level
  147      * @return void
  148      */
  149     protected function _addTree(Zend_Server_Reflection_Node $parent, $level = 0)
  150     {
  151         if ($level >= $this->_sigParamsDepth) {
  152             return;
  153         }
  154 
  155         foreach ($this->_sigParams[$level] as $value) {
  156             $node = new Zend_Server_Reflection_Node($value, $parent);
  157             if ((null !== $value) && ($this->_sigParamsDepth > $level + 1)) {
  158                 $this->_addTree($node, $level + 1);
  159             }
  160         }
  161     }
  162 
  163     /**
  164      * Build the signature tree
  165      *
  166      * Builds a signature tree starting at the return values and descending
  167      * through each method argument. Returns an array of
  168      * {@link Zend_Server_Reflection_Node}s.
  169      *
  170      * @return array
  171      */
  172     protected function _buildTree()
  173     {
  174         $returnTree = array();
  175         foreach ((array) $this->_return as $value) {
  176             $node = new Zend_Server_Reflection_Node($value);
  177             $this->_addTree($node);
  178             $returnTree[] = $node;
  179         }
  180 
  181         return $returnTree;
  182     }
  183 
  184     /**
  185      * Build method signatures
  186      *
  187      * Builds method signatures using the array of return types and the array of
  188      * parameters types
  189      *
  190      * @param array $return Array of return types
  191      * @param string $returnDesc Return value description
  192      * @param array $params Array of arguments (each an array of types)
  193      * @param array $paramDesc Array of parameter descriptions
  194      * @return array
  195      */
  196     protected function _buildSignatures($return, $returnDesc, $paramTypes, $paramDesc)
  197     {
  198         $this->_return         = $return;
  199         $this->_returnDesc     = $returnDesc;
  200         $this->_paramDesc      = $paramDesc;
  201         $this->_sigParams      = $paramTypes;
  202         $this->_sigParamsDepth = count($paramTypes);
  203         $signatureTrees        = $this->_buildTree();
  204         $signatures            = array();
  205 
  206         $endPoints = array();
  207         foreach ($signatureTrees as $root) {
  208             $tmp = $root->getEndPoints();
  209             if (empty($tmp)) {
  210                 $endPoints = array_merge($endPoints, array($root));
  211             } else {
  212                 $endPoints = array_merge($endPoints, $tmp);
  213             }
  214         }
  215 
  216         foreach ($endPoints as $node) {
  217             if (!$node instanceof Zend_Server_Reflection_Node) {
  218                 continue;
  219             }
  220 
  221             $signature = array();
  222             do {
  223                 array_unshift($signature, $node->getValue());
  224                 $node = $node->getParent();
  225             } while ($node instanceof Zend_Server_Reflection_Node);
  226 
  227             $signatures[] = $signature;
  228         }
  229 
  230         // Build prototypes
  231         $params = $this->_reflection->getParameters();
  232         foreach ($signatures as $signature) {
  233             $return = new Zend_Server_Reflection_ReturnValue(array_shift($signature), $this->_returnDesc);
  234             $tmp    = array();
  235             foreach ($signature as $key => $type) {
  236                 $param = new Zend_Server_Reflection_Parameter($params[$key], $type, (isset($this->_paramDesc[$key]) ? $this->_paramDesc[$key] : null));
  237                 $param->setPosition($key);
  238                 $tmp[] = $param;
  239             }
  240 
  241             $this->_prototypes[] = new Zend_Server_Reflection_Prototype($return, $tmp);
  242         }
  243     }
  244 
  245     /**
  246      * Use code reflection to create method signatures
  247      *
  248      * Determines the method help/description text from the function DocBlock
  249      * comment. Determines method signatures using a combination of
  250      * ReflectionFunction and parsing of DocBlock @param and @return values.
  251      *
  252      * @param ReflectionFunction $function
  253      * @return array
  254      */
  255     protected function _reflect()
  256     {
  257         $function           = $this->_reflection;
  258         $helpText           = '';
  259         $signatures         = array();
  260         $returnDesc         = '';
  261         $paramCount         = $function->getNumberOfParameters();
  262         $paramCountRequired = $function->getNumberOfRequiredParameters();
  263         $parameters         = $function->getParameters();
  264         $docBlock           = $function->getDocComment();
  265 
  266         if (!empty($docBlock)) {
  267             // Get help text
  268             if (preg_match(':/\*\*\s*\r?\n\s*\*\s(.*?)\r?\n\s*\*(\s@|/):s', $docBlock, $matches))
  269             {
  270                 $helpText = $matches[1];
  271                 $helpText = preg_replace('/(^\s*\*\s)/m', '', $helpText);
  272                 $helpText = preg_replace('/\r?\n\s*\*\s*(\r?\n)*/s', "\n", $helpText);
  273                 $helpText = trim($helpText);
  274             }
  275 
  276             // Get return type(s) and description
  277             $return     = 'void';
  278             if (preg_match('/@return\s+(\S+)/', $docBlock, $matches)) {
  279                 $return = explode('|', $matches[1]);
  280                 if (preg_match('/@return\s+\S+\s+(.*?)(@|\*\/)/s', $docBlock, $matches))
  281                 {
  282                     $value = $matches[1];
  283                     $value = preg_replace('/\s?\*\s/m', '', $value);
  284                     $value = preg_replace('/\s{2,}/', ' ', $value);
  285                     $returnDesc = trim($value);
  286                 }
  287             }
  288 
  289             // Get param types and description
  290             if (preg_match_all('/@param\s+([^\s]+)/m', $docBlock, $matches)) {
  291                 $paramTypesTmp = $matches[1];
  292                 if (preg_match_all('/@param\s+\S+\s+(\$\S+)\s+(.*?)(?=@|\*\/)/s', $docBlock, $matches))
  293                 {
  294                     $paramDesc = $matches[2];
  295                     foreach ($paramDesc as $key => $value) {
  296                         $value = preg_replace('/\s?\*\s/m', '', $value);
  297                         $value = preg_replace('/\s{2,}/', ' ', $value);
  298                         $paramDesc[$key] = trim($value);
  299                     }
  300                 }
  301             }
  302         } else {
  303             $helpText = $function->getName();
  304             $return   = 'void';
  305 
  306             // Try and auto-determine type, based on reflection
  307             $paramTypesTmp = array();
  308             foreach ($parameters as $i => $param) {
  309                 $paramType = 'mixed';
  310                 if ($param->isArray()) {
  311                     $paramType = 'array';
  312                 }
  313                 $paramTypesTmp[$i] = $paramType;
  314             }
  315         }
  316 
  317         // Set method description
  318         $this->setDescription($helpText);
  319 
  320         // Get all param types as arrays
  321         if (!isset($paramTypesTmp) && (0 < $paramCount)) {
  322             $paramTypesTmp = array_fill(0, $paramCount, 'mixed');
  323         } elseif (!isset($paramTypesTmp)) {
  324             $paramTypesTmp = array();
  325         } elseif (count($paramTypesTmp) < $paramCount) {
  326             $start = $paramCount - count($paramTypesTmp);
  327             for ($i = $start; $i < $paramCount; ++$i) {
  328                 $paramTypesTmp[$i] = 'mixed';
  329             }
  330         }
  331 
  332         // Get all param descriptions as arrays
  333         if (!isset($paramDesc) && (0 < $paramCount)) {
  334             $paramDesc = array_fill(0, $paramCount, '');
  335         } elseif (!isset($paramDesc)) {
  336             $paramDesc = array();
  337         } elseif (count($paramDesc) < $paramCount) {
  338             $start = $paramCount - count($paramDesc);
  339             for ($i = $start; $i < $paramCount; ++$i) {
  340                 $paramDesc[$i] = '';
  341             }
  342         }
  343 
  344         if (count($paramTypesTmp) != $paramCount) {
  345             throw new Zend_Server_Reflection_Exception(
  346                'Variable number of arguments is not supported for services (except optional parameters). '
  347              . 'Number of function arguments in ' . $function->getDeclaringClass()->getName() . '::'
  348              . $function->getName() . '() must correspond to actual number of arguments described in the '
  349              . 'docblock.');
  350         }
  351 
  352         $paramTypes = array();
  353         foreach ($paramTypesTmp as $i => $param) {
  354             $tmp = explode('|', $param);
  355             if ($parameters[$i]->isOptional()) {
  356                 array_unshift($tmp, null);
  357             }
  358             $paramTypes[] = $tmp;
  359         }
  360 
  361         $this->_buildSignatures($return, $returnDesc, $paramTypes, $paramDesc);
  362     }
  363 
  364 
  365     /**
  366      * Proxy reflection calls
  367      *
  368      * @param string $method
  369      * @param array $args
  370      * @return mixed
  371      */
  372     public function __call($method, $args)
  373     {
  374         if (method_exists($this->_reflection, $method)) {
  375             return call_user_func_array(array($this->_reflection, $method), $args);
  376         }
  377 
  378         throw new Zend_Server_Reflection_Exception('Invalid reflection method ("' .$method. '")');
  379     }
  380 
  381     /**
  382      * Retrieve configuration parameters
  383      *
  384      * Values are retrieved by key from {@link $_config}. Returns null if no
  385      * value found.
  386      *
  387      * @param string $key
  388      * @return mixed
  389      */
  390     public function __get($key)
  391     {
  392         if (isset($this->_config[$key])) {
  393             return $this->_config[$key];
  394         }
  395 
  396         return null;
  397     }
  398 
  399     /**
  400      * Set configuration parameters
  401      *
  402      * Values are stored by $key in {@link $_config}.
  403      *
  404      * @param string $key
  405      * @param mixed $value
  406      * @return void
  407      */
  408     public function __set($key, $value)
  409     {
  410         $this->_config[$key] = $value;
  411     }
  412 
  413     /**
  414      * Set method's namespace
  415      *
  416      * @param string $namespace
  417      * @return void
  418      */
  419     public function setNamespace($namespace)
  420     {
  421         if (empty($namespace)) {
  422             $this->_namespace = '';
  423             return;
  424         }
  425 
  426         if (!is_string($namespace) || !preg_match('/[a-z0-9_\.]+/i', $namespace)) {
  427             throw new Zend_Server_Reflection_Exception('Invalid namespace');
  428         }
  429 
  430         $this->_namespace = $namespace;
  431     }
  432 
  433     /**
  434      * Return method's namespace
  435      *
  436      * @return string
  437      */
  438     public function getNamespace()
  439     {
  440         return $this->_namespace;
  441     }
  442 
  443     /**
  444      * Set the description
  445      *
  446      * @param string $string
  447      * @return void
  448      */
  449     public function setDescription($string)
  450     {
  451         if (!is_string($string)) {
  452             throw new Zend_Server_Reflection_Exception('Invalid description');
  453         }
  454 
  455         $this->_description = $string;
  456     }
  457 
  458     /**
  459      * Retrieve the description
  460      *
  461      * @return void
  462      */
  463     public function getDescription()
  464     {
  465         return $this->_description;
  466     }
  467 
  468     /**
  469      * Retrieve all prototypes as array of
  470      * {@link Zend_Server_Reflection_Prototype Zend_Server_Reflection_Prototypes}
  471      *
  472      * @return array
  473      */
  474     public function getPrototypes()
  475     {
  476         return $this->_prototypes;
  477     }
  478 
  479     /**
  480      * Retrieve additional invocation arguments
  481      *
  482      * @return array
  483      */
  484     public function getInvokeArguments()
  485     {
  486         return $this->_argv;
  487     }
  488 
  489     /**
  490      * Wakeup from serialization
  491      *
  492      * Reflection needs explicit instantiation to work correctly. Re-instantiate
  493      * reflection object on wakeup.
  494      *
  495      * @return void
  496      */
  497     public function __wakeup()
  498     {
  499         if ($this->_reflection instanceof ReflectionMethod) {
  500             $class = new ReflectionClass($this->_class);
  501             $this->_reflection = new ReflectionMethod($class->newInstance(), $this->getName());
  502         } else {
  503             $this->_reflection = new ReflectionFunction($this->getName());
  504         }
  505     }
  506 }