|
Moodle
2.2.1
http://www.collinsharper.com
|
00001 <?php 00024 require_once 'Zend/Server/Reflection/Node.php'; 00025 00029 require_once 'Zend/Server/Reflection/Parameter.php'; 00030 00034 require_once 'Zend/Server/Reflection/Prototype.php'; 00035 00053 abstract class Zend_Server_Reflection_Function_Abstract 00054 { 00058 protected $_reflection; 00059 00064 protected $_argv = array(); 00065 00073 protected $_config = array(); 00074 00079 protected $_class; 00080 00085 protected $_description = ''; 00086 00091 protected $_namespace; 00092 00097 protected $_prototypes = array(); 00098 00099 private $_return; 00100 private $_returnDesc; 00101 private $_paramDesc; 00102 private $_sigParams; 00103 private $_sigParamsDepth; 00104 00110 public function __construct(Reflector $r, $namespace = null, $argv = array()) 00111 { 00112 // In PHP 5.1.x, ReflectionMethod extends ReflectionFunction. In 5.2.x, 00113 // both extend ReflectionFunctionAbstract. So, we can't do normal type 00114 // hinting in the prototype, but instead need to do some explicit 00115 // testing here. 00116 if ((!$r instanceof ReflectionFunction) 00117 && (!$r instanceof ReflectionMethod)) { 00118 require_once 'Zend/Server/Reflection/Exception.php'; 00119 throw new Zend_Server_Reflection_Exception('Invalid reflection class'); 00120 } 00121 $this->_reflection = $r; 00122 00123 // Determine namespace 00124 if (null !== $namespace){ 00125 $this->setNamespace($namespace); 00126 } 00127 00128 // Determine arguments 00129 if (is_array($argv)) { 00130 $this->_argv = $argv; 00131 } 00132 00133 // If method call, need to store some info on the class 00134 if ($r instanceof ReflectionMethod) { 00135 $this->_class = $r->getDeclaringClass()->getName(); 00136 } 00137 00138 // Perform some introspection 00139 $this->_reflect(); 00140 } 00141 00153 protected function _addTree(Zend_Server_Reflection_Node $parent, $level = 0) 00154 { 00155 if ($level >= $this->_sigParamsDepth) { 00156 return; 00157 } 00158 00159 foreach ($this->_sigParams[$level] as $value) { 00160 $node = new Zend_Server_Reflection_Node($value, $parent); 00161 if ((null !== $value) && ($this->_sigParamsDepth > $level + 1)) { 00162 $this->_addTree($node, $level + 1); 00163 } 00164 } 00165 } 00166 00176 protected function _buildTree() 00177 { 00178 $returnTree = array(); 00179 foreach ((array) $this->_return as $value) { 00180 $node = new Zend_Server_Reflection_Node($value); 00181 $this->_addTree($node); 00182 $returnTree[] = $node; 00183 } 00184 00185 return $returnTree; 00186 } 00187 00200 protected function _buildSignatures($return, $returnDesc, $paramTypes, $paramDesc) 00201 { 00202 $this->_return = $return; 00203 $this->_returnDesc = $returnDesc; 00204 $this->_paramDesc = $paramDesc; 00205 $this->_sigParams = $paramTypes; 00206 $this->_sigParamsDepth = count($paramTypes); 00207 $signatureTrees = $this->_buildTree(); 00208 $signatures = array(); 00209 00210 $endPoints = array(); 00211 foreach ($signatureTrees as $root) { 00212 $tmp = $root->getEndPoints(); 00213 if (empty($tmp)) { 00214 $endPoints = array_merge($endPoints, array($root)); 00215 } else { 00216 $endPoints = array_merge($endPoints, $tmp); 00217 } 00218 } 00219 00220 foreach ($endPoints as $node) { 00221 if (!$node instanceof Zend_Server_Reflection_Node) { 00222 continue; 00223 } 00224 00225 $signature = array(); 00226 do { 00227 array_unshift($signature, $node->getValue()); 00228 $node = $node->getParent(); 00229 } while ($node instanceof Zend_Server_Reflection_Node); 00230 00231 $signatures[] = $signature; 00232 } 00233 00234 // Build prototypes 00235 $params = $this->_reflection->getParameters(); 00236 foreach ($signatures as $signature) { 00237 $return = new Zend_Server_Reflection_ReturnValue(array_shift($signature), $this->_returnDesc); 00238 $tmp = array(); 00239 foreach ($signature as $key => $type) { 00240 $param = new Zend_Server_Reflection_Parameter($params[$key], $type, (isset($this->_paramDesc[$key]) ? $this->_paramDesc[$key] : null)); 00241 $param->setPosition($key); 00242 $tmp[] = $param; 00243 } 00244 00245 $this->_prototypes[] = new Zend_Server_Reflection_Prototype($return, $tmp); 00246 } 00247 } 00248 00259 protected function _reflect() 00260 { 00261 $function = $this->_reflection; 00262 $helpText = ''; 00263 $signatures = array(); 00264 $returnDesc = ''; 00265 $paramCount = $function->getNumberOfParameters(); 00266 $paramCountRequired = $function->getNumberOfRequiredParameters(); 00267 $parameters = $function->getParameters(); 00268 $docBlock = $function->getDocComment(); 00269 00270 if (!empty($docBlock)) { 00271 // Get help text 00272 if (preg_match(':/\*\*\s*\r?\n\s*\*\s(.*?)\r?\n\s*\*(\s@|/):s', $docBlock, $matches)) 00273 { 00274 $helpText = $matches[1]; 00275 $helpText = preg_replace('/(^\s*\*\s)/m', '', $helpText); 00276 $helpText = preg_replace('/\r?\n\s*\*\s*(\r?\n)*/s', "\n", $helpText); 00277 $helpText = trim($helpText); 00278 } 00279 00280 // Get return type(s) and description 00281 $return = 'void'; 00282 if (preg_match('/@return\s+(\S+)/', $docBlock, $matches)) { 00283 $return = explode('|', $matches[1]); 00284 if (preg_match('/@return\s+\S+\s+(.*?)(@|\*\/)/s', $docBlock, $matches)) 00285 { 00286 $value = $matches[1]; 00287 $value = preg_replace('/\s?\*\s/m', '', $value); 00288 $value = preg_replace('/\s{2,}/', ' ', $value); 00289 $returnDesc = trim($value); 00290 } 00291 } 00292 00293 // Get param types and description 00294 if (preg_match_all('/@param\s+([^\s]+)/m', $docBlock, $matches)) { 00295 $paramTypesTmp = $matches[1]; 00296 if (preg_match_all('/@param\s+\S+\s+(\$\S+)\s+(.*?)(@|\*\/)/s', $docBlock, $matches)) 00297 { 00298 $paramDesc = $matches[2]; 00299 foreach ($paramDesc as $key => $value) { 00300 $value = preg_replace('/\s?\*\s/m', '', $value); 00301 $value = preg_replace('/\s{2,}/', ' ', $value); 00302 $paramDesc[$key] = trim($value); 00303 } 00304 } 00305 } 00306 } else { 00307 $helpText = $function->getName(); 00308 $return = 'void'; 00309 } 00310 00311 // Set method description 00312 $this->setDescription($helpText); 00313 00314 // Get all param types as arrays 00315 if (!isset($paramTypesTmp) && (0 < $paramCount)) { 00316 $paramTypesTmp = array_fill(0, $paramCount, 'mixed'); 00317 } elseif (!isset($paramTypesTmp)) { 00318 $paramTypesTmp = array(); 00319 } elseif (count($paramTypesTmp) < $paramCount) { 00320 $start = $paramCount - count($paramTypesTmp); 00321 for ($i = $start; $i < $paramCount; ++$i) { 00322 $paramTypesTmp[$i] = 'mixed'; 00323 } 00324 } 00325 00326 // Get all param descriptions as arrays 00327 if (!isset($paramDesc) && (0 < $paramCount)) { 00328 $paramDesc = array_fill(0, $paramCount, ''); 00329 } elseif (!isset($paramDesc)) { 00330 $paramDesc = array(); 00331 } elseif (count($paramDesc) < $paramCount) { 00332 $start = $paramCount - count($paramDesc); 00333 for ($i = $start; $i < $paramCount; ++$i) { 00334 $paramDesc[$i] = ''; 00335 } 00336 } 00337 00338 if (count($paramTypesTmp) != $paramCount) { 00339 require_once 'Zend/Server/Reflection/Exception.php'; 00340 throw new Zend_Server_Reflection_Exception( 00341 'Variable number of arguments is not supported for services (except optional parameters). ' 00342 . 'Number of function arguments must correspond to actual number of arguments described in a docblock ' 00343 . '(function was ' . $function->getName() . ')'); 00344 } 00345 00346 $paramTypes = array(); 00347 foreach ($paramTypesTmp as $i => $param) { 00348 $tmp = explode('|', $param); 00349 if ($parameters[$i]->isOptional()) { 00350 array_unshift($tmp, null); 00351 } 00352 $paramTypes[] = $tmp; 00353 } 00354 00355 $this->_buildSignatures($return, $returnDesc, $paramTypes, $paramDesc); 00356 } 00357 00358 00366 public function __call($method, $args) 00367 { 00368 if (method_exists($this->_reflection, $method)) { 00369 return call_user_func_array(array($this->_reflection, $method), $args); 00370 } 00371 00372 require_once 'Zend/Server/Reflection/Exception.php'; 00373 throw new Zend_Server_Reflection_Exception('Invalid reflection method ("' .$method. '")'); 00374 } 00375 00385 public function __get($key) 00386 { 00387 if (isset($this->_config[$key])) { 00388 return $this->_config[$key]; 00389 } 00390 00391 return null; 00392 } 00393 00403 public function __set($key, $value) 00404 { 00405 $this->_config[$key] = $value; 00406 } 00407 00414 public function setNamespace($namespace) 00415 { 00416 if (empty($namespace)) { 00417 $this->_namespace = ''; 00418 return; 00419 } 00420 00421 if (!is_string($namespace) || !preg_match('/[a-z0-9_\.]+/i', $namespace)) { 00422 require_once 'Zend/Server/Reflection/Exception.php'; 00423 throw new Zend_Server_Reflection_Exception('Invalid namespace'); 00424 } 00425 00426 $this->_namespace = $namespace; 00427 } 00428 00434 public function getNamespace() 00435 { 00436 return $this->_namespace; 00437 } 00438 00445 public function setDescription($string) 00446 { 00447 if (!is_string($string)) { 00448 require_once 'Zend/Server/Reflection/Exception.php'; 00449 throw new Zend_Server_Reflection_Exception('Invalid description'); 00450 } 00451 00452 $this->_description = $string; 00453 } 00454 00460 public function getDescription() 00461 { 00462 return $this->_description; 00463 } 00464 00471 public function getPrototypes() 00472 { 00473 return $this->_prototypes; 00474 } 00475 00481 public function getInvokeArguments() 00482 { 00483 return $this->_argv; 00484 } 00485 00494 public function __wakeup() 00495 { 00496 if ($this->_reflection instanceof ReflectionMethod) { 00497 $class = new ReflectionClass($this->_class); 00498 $this->_reflection = new ReflectionMethod($class->newInstance(), $this->getName()); 00499 } else { 00500 $this->_reflection = new ReflectionFunction($this->getName()); 00501 } 00502 } 00503 }