torrentpier-lts/library/Zend/Code/Reflection/FunctionReflection.php

270 lines
7.9 KiB
PHP
Raw Normal View History

<?php
/**
* Zend Framework (http://framework.zend.com/)
*
* @link http://github.com/zendframework/zf2 for the canonical source repository
2023-04-01 09:03:34 +03:00
* @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
namespace Zend\Code\Reflection;
use ReflectionFunction;
class FunctionReflection extends ReflectionFunction implements ReflectionInterface
{
/**
* Constant use in @MethodReflection to display prototype as an array
*/
const PROTOTYPE_AS_ARRAY = 'prototype_as_array';
/**
* Constant use in @MethodReflection to display prototype as a string
*/
const PROTOTYPE_AS_STRING = 'prototype_as_string';
/**
* Get function DocBlock
*
* @throws Exception\InvalidArgumentException
* @return DocBlockReflection
*/
public function getDocBlock()
{
if ('' == ($comment = $this->getDocComment())) {
throw new Exception\InvalidArgumentException(sprintf(
'%s does not have a DocBlock',
$this->getName()
));
}
$instance = new DocBlockReflection($comment);
return $instance;
}
/**
* Get start line (position) of function
*
* @param bool $includeDocComment
* @return int
*/
public function getStartLine($includeDocComment = false)
{
if ($includeDocComment) {
if ($this->getDocComment() != '') {
return $this->getDocBlock()->getStartLine();
}
}
return parent::getStartLine();
}
/**
* Get contents of function
*
* @param bool $includeDocBlock
* @return string
*/
public function getContents($includeDocBlock = true)
{
$fileName = $this->getFileName();
if (false === $fileName) {
return '';
}
$startLine = $this->getStartLine();
$endLine = $this->getEndLine();
// eval'd protect
if (preg_match('#\((\d+)\) : eval\(\)\'d code$#', $fileName, $matches)) {
$fileName = preg_replace('#\(\d+\) : eval\(\)\'d code$#', '', $fileName);
$startLine = $endLine = $matches[1];
}
$lines = array_slice(
file($fileName, FILE_IGNORE_NEW_LINES),
$startLine - 1,
($endLine - ($startLine - 1)),
true
);
$functionLine = implode("\n", $lines);
$content = '';
if ($this->isClosure()) {
preg_match('#function\s*\([^\)]*\)\s*(use\s*\([^\)]+\))?\s*\{(.*\;)?\s*\}#s', $functionLine, $matches);
if (isset($matches[0])) {
$content = $matches[0];
}
} else {
$name = substr($this->getName(), strrpos($this->getName(), '\\')+1);
preg_match('#function\s+' . preg_quote($name) . '\s*\([^\)]*\)\s*{([^{}]+({[^}]+})*[^}]+)?}#', $functionLine, $matches);
if (isset($matches[0])) {
$content = $matches[0];
}
}
$docComment = $this->getDocComment();
return $includeDocBlock && $docComment ? $docComment . "\n" . $content : $content;
}
/**
* Get method prototype
*
* @return array
*/
public function getPrototype($format = FunctionReflection::PROTOTYPE_AS_ARRAY)
{
$returnType = 'mixed';
$docBlock = $this->getDocBlock();
if ($docBlock) {
$return = $docBlock->getTag('return');
$returnTypes = $return->getTypes();
$returnType = count($returnTypes) > 1 ? implode('|', $returnTypes) : $returnTypes[0];
}
$prototype = array(
'namespace' => $this->getNamespaceName(),
'name' => substr($this->getName(), strlen($this->getNamespaceName()) + 1),
'return' => $returnType,
'arguments' => array(),
);
$parameters = $this->getParameters();
foreach ($parameters as $parameter) {
$prototype['arguments'][$parameter->getName()] = array(
'type' => $parameter->getType(),
'required' => !$parameter->isOptional(),
'by_ref' => $parameter->isPassedByReference(),
'default' => $parameter->isDefaultValueAvailable() ? $parameter->getDefaultValue() : null,
);
}
if ($format == FunctionReflection::PROTOTYPE_AS_STRING) {
$line = $prototype['return'] . ' ' . $prototype['name'] . '(';
$args = array();
foreach ($prototype['arguments'] as $name => $argument) {
$argsLine = ($argument['type'] ? $argument['type'] . ' ' : '') . ($argument['by_ref'] ? '&' : '') . '$' . $name;
if (!$argument['required']) {
$argsLine .= ' = ' . var_export($argument['default'], true);
}
$args[] = $argsLine;
}
$line .= implode(', ', $args);
$line .= ')';
return $line;
}
return $prototype;
}
/**
* Get function parameters
*
* @return ParameterReflection[]
*/
public function getParameters()
{
$phpReflections = parent::getParameters();
$zendReflections = array();
while ($phpReflections && ($phpReflection = array_shift($phpReflections))) {
$instance = new ParameterReflection($this->getName(), $phpReflection->getName());
$zendReflections[] = $instance;
unset($phpReflection);
}
unset($phpReflections);
return $zendReflections;
}
/**
* Get return type tag
*
* @throws Exception\InvalidArgumentException
* @return DocBlockReflection
*/
public function getReturn()
{
$docBlock = $this->getDocBlock();
if (!$docBlock->hasTag('return')) {
throw new Exception\InvalidArgumentException(
'Function does not specify an @return annotation tag; cannot determine return type'
);
}
$tag = $docBlock->getTag('return');
return new DocBlockReflection('@return ' . $tag->getDescription());
}
/**
* Get method body
*
2023-04-01 09:03:34 +03:00
* @return string|false
*/
public function getBody()
{
$fileName = $this->getFileName();
if (false === $fileName) {
throw new Exception\InvalidArgumentException(
'Cannot determine internals functions body'
);
}
$startLine = $this->getStartLine();
$endLine = $this->getEndLine();
// eval'd protect
if (preg_match('#\((\d+)\) : eval\(\)\'d code$#', $fileName, $matches)) {
$fileName = preg_replace('#\(\d+\) : eval\(\)\'d code$#', '', $fileName);
$startLine = $endLine = $matches[1];
}
$lines = array_slice(
file($fileName, FILE_IGNORE_NEW_LINES),
$startLine - 1,
($endLine - ($startLine - 1)),
true
);
$functionLine = implode("\n", $lines);
$body = false;
if ($this->isClosure()) {
preg_match('#function\s*\([^\)]*\)\s*(use\s*\([^\)]+\))?\s*\{(.*\;)\s*\}#s', $functionLine, $matches);
if (isset($matches[2])) {
$body = $matches[2];
}
} else {
$name = substr($this->getName(), strrpos($this->getName(), '\\')+1);
preg_match('#function\s+' . $name . '\s*\([^\)]*\)\s*{([^{}]+({[^}]+})*[^}]+)}#', $functionLine, $matches);
if (isset($matches[1])) {
$body = $matches[1];
}
}
return $body;
}
2023-04-01 09:03:34 +03:00
/**
* @return string
*/
public function toString()
{
return $this->__toString();
}
/**
* Required due to bug in php
*
* @return string
*/
public function __toString()
{
return parent::__toString();
}
}