"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 }