1424 lines
33 KiB
PHP
1424 lines
33 KiB
PHP
<?php
|
|
|
|
/**
|
|
* ApiGen 2.8.0 - API documentation generator for PHP 5.3+
|
|
*
|
|
* Copyright (c) 2010-2011 David Grudl (http://davidgrudl.com)
|
|
* Copyright (c) 2011-2012 Jaroslav Hanslík (https://github.com/kukulich)
|
|
* Copyright (c) 2011-2012 Ondřej Nešpor (https://github.com/Andrewsville)
|
|
*
|
|
* For the full copyright and license information, please view
|
|
* the file LICENSE.md that was distributed with this source code.
|
|
*/
|
|
|
|
namespace ApiGen;
|
|
|
|
use TokenReflection, TokenReflection\IReflectionClass, TokenReflection\IReflectionMethod, TokenReflection\IReflectionProperty, TokenReflection\IReflectionConstant;
|
|
use ReflectionMethod as InternalReflectionMethod, ReflectionProperty as InternalReflectionProperty;
|
|
use InvalidArgumentException;
|
|
|
|
/**
|
|
* Class reflection envelope.
|
|
*
|
|
* Alters TokenReflection\IReflectionClass functionality for ApiGen.
|
|
*/
|
|
class ReflectionClass extends ReflectionElement
|
|
{
|
|
/**
|
|
* Access level for methods.
|
|
*
|
|
* @var integer
|
|
*/
|
|
private static $methodAccessLevels = false;
|
|
|
|
/**
|
|
* Access level for properties.
|
|
*
|
|
* @var integer
|
|
*/
|
|
private static $propertyAccessLevels = false;
|
|
|
|
/**
|
|
* Cache for list of parent classes.
|
|
*
|
|
* @var array
|
|
*/
|
|
private $parentClasses;
|
|
|
|
/**
|
|
* Cache for list of own methods.
|
|
*
|
|
* @var array
|
|
*/
|
|
private $ownMethods;
|
|
|
|
/**
|
|
* Cache for list of own magic methods.
|
|
*
|
|
* @var array
|
|
*/
|
|
private $ownMagicMethods;
|
|
|
|
/**
|
|
* Cache for list of own properties.
|
|
*
|
|
* @var array
|
|
*/
|
|
private $ownProperties;
|
|
|
|
/**
|
|
* Cache for list of own magic properties.
|
|
*
|
|
* @var array
|
|
*/
|
|
private $ownMagicProperties;
|
|
|
|
/**
|
|
* Cache for list of own constants.
|
|
*
|
|
* @var array
|
|
*/
|
|
private $ownConstants;
|
|
|
|
/**
|
|
* Cache for list of all methods.
|
|
*
|
|
* @var array
|
|
*/
|
|
private $methods;
|
|
|
|
/**
|
|
* Cache for list of all properties.
|
|
*
|
|
* @var array
|
|
*/
|
|
private $properties;
|
|
|
|
/**
|
|
* Cache for list of all constants.
|
|
*
|
|
* @var array
|
|
*/
|
|
private $constants;
|
|
|
|
/**
|
|
* Constructor.
|
|
*
|
|
* Sets the inspected class reflection.
|
|
*
|
|
* @param \TokenReflection\IReflectionClass $reflection Inspected class reflection
|
|
* @param \ApiGen\Generator $generator ApiGen generator
|
|
*/
|
|
public function __construct(IReflectionClass $reflection, Generator $generator)
|
|
{
|
|
parent::__construct($reflection, $generator);
|
|
|
|
if (false === self::$methodAccessLevels) {
|
|
if (count(self::$config->accessLevels) < 3) {
|
|
self::$methodAccessLevels = 0;
|
|
self::$propertyAccessLevels = 0;
|
|
|
|
foreach (self::$config->accessLevels as $level) {
|
|
switch (strtolower($level)) {
|
|
case 'public':
|
|
self::$methodAccessLevels |= InternalReflectionMethod::IS_PUBLIC;
|
|
self::$propertyAccessLevels |= InternalReflectionProperty::IS_PUBLIC;
|
|
break;
|
|
case 'protected':
|
|
self::$methodAccessLevels |= InternalReflectionMethod::IS_PROTECTED;
|
|
self::$propertyAccessLevels |= InternalReflectionProperty::IS_PROTECTED;
|
|
break;
|
|
case 'private':
|
|
self::$methodAccessLevels |= InternalReflectionMethod::IS_PRIVATE;
|
|
self::$propertyAccessLevels |= InternalReflectionProperty::IS_PRIVATE;
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
} else {
|
|
self::$methodAccessLevels = null;
|
|
self::$propertyAccessLevels = null;
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Returns the unqualified name (UQN).
|
|
*
|
|
* @return string
|
|
*/
|
|
public function getShortName()
|
|
{
|
|
return $this->reflection->getShortName();
|
|
}
|
|
|
|
/**
|
|
* Returns modifiers.
|
|
*
|
|
* @return array
|
|
*/
|
|
public function getModifiers()
|
|
{
|
|
return $this->reflection->getModifiers();
|
|
}
|
|
|
|
/**
|
|
* Returns if the class is abstract.
|
|
*
|
|
* @return boolean
|
|
*/
|
|
public function isAbstract()
|
|
{
|
|
return $this->reflection->isAbstract();
|
|
}
|
|
|
|
/**
|
|
* Returns if the class is final.
|
|
*
|
|
* @return boolean
|
|
*/
|
|
public function isFinal()
|
|
{
|
|
return $this->reflection->isFinal();
|
|
}
|
|
|
|
/**
|
|
* Returns if the class is an interface.
|
|
*
|
|
* @return boolean
|
|
*/
|
|
public function isInterface()
|
|
{
|
|
return $this->reflection->isInterface();
|
|
}
|
|
|
|
/**
|
|
* Returns if the class is an exception or its descendant.
|
|
*
|
|
* @return boolean
|
|
*/
|
|
public function isException()
|
|
{
|
|
return $this->reflection->isException();
|
|
}
|
|
|
|
/**
|
|
* Returns if the current class is a subclass of the given class.
|
|
*
|
|
* @param string $class Class name
|
|
* @return boolean
|
|
*/
|
|
public function isSubclassOf($class)
|
|
{
|
|
return $this->reflection->isSubclassOf($class);
|
|
}
|
|
|
|
/**
|
|
* Returns visible methods.
|
|
*
|
|
* @return array
|
|
*/
|
|
public function getMethods()
|
|
{
|
|
if (null === $this->methods) {
|
|
$this->methods = $this->getOwnMethods();
|
|
foreach ($this->reflection->getMethods(self::$methodAccessLevels) as $method) {
|
|
if (isset($this->methods[$method->getName()])) {
|
|
continue;
|
|
}
|
|
$apiMethod = new ReflectionMethod($method, self::$generator);
|
|
if (!$this->isDocumented() || $apiMethod->isDocumented()) {
|
|
$this->methods[$method->getName()] = $apiMethod;
|
|
}
|
|
}
|
|
}
|
|
return $this->methods;
|
|
}
|
|
|
|
/**
|
|
* Returns visible methods declared by inspected class.
|
|
*
|
|
* @return array
|
|
*/
|
|
public function getOwnMethods()
|
|
{
|
|
if (null === $this->ownMethods) {
|
|
$this->ownMethods = array();
|
|
foreach ($this->reflection->getOwnMethods(self::$methodAccessLevels) as $method) {
|
|
$apiMethod = new ReflectionMethod($method, self::$generator);
|
|
if (!$this->isDocumented() || $apiMethod->isDocumented()) {
|
|
$this->ownMethods[$method->getName()] = $apiMethod;
|
|
}
|
|
}
|
|
}
|
|
return $this->ownMethods;
|
|
}
|
|
|
|
/**
|
|
* Returns visible magic methods.
|
|
*
|
|
* @return array
|
|
*/
|
|
public function getMagicMethods()
|
|
{
|
|
$methods = $this->getOwnMagicMethods();
|
|
|
|
$parent = $this->getParentClass();
|
|
while ($parent) {
|
|
foreach ($parent->getOwnMagicMethods() as $method) {
|
|
if (isset($methods[$method->getName()])) {
|
|
continue;
|
|
}
|
|
|
|
if (!$this->isDocumented() || $method->isDocumented()) {
|
|
$methods[$method->getName()] = $method;
|
|
}
|
|
}
|
|
$parent = $parent->getParentClass();
|
|
}
|
|
|
|
foreach ($this->getTraits() as $trait) {
|
|
foreach ($trait->getOwnMagicMethods() as $method) {
|
|
if (isset($methods[$method->getName()])) {
|
|
continue;
|
|
}
|
|
|
|
if (!$this->isDocumented() || $method->isDocumented()) {
|
|
$methods[$method->getName()] = $method;
|
|
}
|
|
}
|
|
}
|
|
|
|
return $methods;
|
|
}
|
|
|
|
/**
|
|
* Returns visible magic methods declared by inspected class.
|
|
*
|
|
* @return array
|
|
*/
|
|
public function getOwnMagicMethods()
|
|
{
|
|
if (null === $this->ownMagicMethods) {
|
|
$this->ownMagicMethods = array();
|
|
|
|
if (!(self::$methodAccessLevels & InternalReflectionMethod::IS_PUBLIC) || false === $this->getDocComment()) {
|
|
return $this->ownMagicMethods;
|
|
}
|
|
|
|
$annotations = $this->getAnnotation('method');
|
|
if (null === $annotations) {
|
|
return $this->ownMagicMethods;
|
|
}
|
|
|
|
foreach ($annotations as $annotation) {
|
|
if (!preg_match('~^(?:([\\w\\\\]+(?:\\|[\\w\\\\]+)*)\\s+)?(&)?\\s*(\\w+)\\s*\\(\\s*(.*)\\s*\\)\\s*(.*|$)~s', $annotation, $matches)) {
|
|
// Wrong annotation format
|
|
continue;
|
|
}
|
|
|
|
list(, $returnTypeHint, $returnsReference, $name, $args, $shortDescription) = $matches;
|
|
|
|
$doc = $this->getDocComment();
|
|
$tmp = $annotation;
|
|
if ($delimiter = strpos($annotation, "\n")) {
|
|
$tmp = substr($annotation, 0, $delimiter);
|
|
}
|
|
|
|
$startLine = $this->getStartLine() + substr_count(substr($doc, 0, strpos($doc, $tmp)), "\n");
|
|
$endLine = $startLine + substr_count($annotation, "\n");
|
|
|
|
$method = new ReflectionMethodMagic(null, self::$generator);
|
|
$method
|
|
->setName($name)
|
|
->setShortDescription(str_replace("\n", ' ', $shortDescription))
|
|
->setStartLine($startLine)
|
|
->setEndLine($endLine)
|
|
->setReturnsReference('&' === $returnsReference)
|
|
->setDeclaringClass($this)
|
|
->addAnnotation('return', $returnTypeHint);
|
|
|
|
$this->ownMagicMethods[$name] = $method;
|
|
|
|
$parameters = array();
|
|
foreach (array_filter(preg_split('~\\s*,\\s*~', $args)) as $position => $arg) {
|
|
if (!preg_match('~^(?:([\\w\\\\]+(?:\\|[\\w\\\\]+)*)\\s+)?(&)?\\s*\\$(\\w+)(?:\\s*=\\s*(.*))?($)~s', $arg, $matches)) {
|
|
// Wrong annotation format
|
|
continue;
|
|
}
|
|
|
|
list(, $typeHint, $passedByReference, $name, $defaultValueDefinition) = $matches;
|
|
|
|
if (empty($typeHint)) {
|
|
$typeHint = 'mixed';
|
|
}
|
|
|
|
$parameter = new ReflectionParameterMagic(null, self::$generator);
|
|
$parameter
|
|
->setName($name)
|
|
->setPosition($position)
|
|
->setTypeHint($typeHint)
|
|
->setDefaultValueDefinition($defaultValueDefinition)
|
|
->setUnlimited(false)
|
|
->setPassedByReference('&' === $passedByReference)
|
|
->setDeclaringFunction($method);
|
|
|
|
$parameters[$name] = $parameter;
|
|
|
|
$method->addAnnotation('param', ltrim(sprintf('%s $%s', $typeHint, $name)));
|
|
}
|
|
$method->setParameters($parameters);
|
|
}
|
|
}
|
|
return $this->ownMagicMethods;
|
|
}
|
|
|
|
/**
|
|
* Returns visible methods declared by traits.
|
|
*
|
|
* @return array
|
|
*/
|
|
public function getTraitMethods()
|
|
{
|
|
$methods = array();
|
|
foreach ($this->reflection->getTraitMethods(self::$methodAccessLevels) as $method) {
|
|
$apiMethod = new ReflectionMethod($method, self::$generator);
|
|
if (!$this->isDocumented() || $apiMethod->isDocumented()) {
|
|
$methods[$method->getName()] = $apiMethod;
|
|
}
|
|
}
|
|
return $methods;
|
|
}
|
|
|
|
/**
|
|
* Returns a method reflection.
|
|
*
|
|
* @param string $name Method name
|
|
* @return \ApiGen\ReflectionMethod
|
|
* @throws \InvalidArgumentException If required method does not exist.
|
|
*/
|
|
public function getMethod($name)
|
|
{
|
|
if ($this->hasMethod($name)) {
|
|
return $this->methods[$name];
|
|
}
|
|
|
|
throw new InvalidArgumentException(sprintf('Method %s does not exist in class %s', $name, $this->reflection->getName()));
|
|
}
|
|
|
|
/**
|
|
* Returns visible properties.
|
|
*
|
|
* @return array
|
|
*/
|
|
public function getProperties()
|
|
{
|
|
if (null === $this->properties) {
|
|
$this->properties = $this->getOwnProperties();
|
|
foreach ($this->reflection->getProperties(self::$propertyAccessLevels) as $property) {
|
|
if (isset($this->properties[$property->getName()])) {
|
|
continue;
|
|
}
|
|
$apiProperty = new ReflectionProperty($property, self::$generator);
|
|
if (!$this->isDocumented() || $apiProperty->isDocumented()) {
|
|
$this->properties[$property->getName()] = $apiProperty;
|
|
}
|
|
}
|
|
}
|
|
return $this->properties;
|
|
}
|
|
|
|
/**
|
|
* Returns visible magic properties.
|
|
*
|
|
* @return array
|
|
*/
|
|
public function getMagicProperties()
|
|
{
|
|
$properties = $this->getOwnMagicProperties();
|
|
|
|
$parent = $this->getParentClass();
|
|
while ($parent) {
|
|
foreach ($parent->getOwnMagicProperties() as $property) {
|
|
if (isset($properties[$method->getName()])) {
|
|
continue;
|
|
}
|
|
|
|
if (!$this->isDocumented() || $property->isDocumented()) {
|
|
$properties[$property->getName()] = $property;
|
|
}
|
|
}
|
|
$parent = $parent->getParentClass();
|
|
}
|
|
|
|
foreach ($this->getTraits() as $trait) {
|
|
foreach ($trait->getOwnMagicProperties() as $property) {
|
|
if (isset($properties[$method->getName()])) {
|
|
continue;
|
|
}
|
|
|
|
if (!$this->isDocumented() || $property->isDocumented()) {
|
|
$properties[$property->getName()] = $property;
|
|
}
|
|
}
|
|
}
|
|
|
|
return $properties;
|
|
}
|
|
|
|
/**
|
|
* Returns visible properties declared by inspected class.
|
|
*
|
|
* @return array
|
|
*/
|
|
public function getOwnProperties()
|
|
{
|
|
if (null === $this->ownProperties) {
|
|
$this->ownProperties = array();
|
|
foreach ($this->reflection->getOwnProperties(self::$propertyAccessLevels) as $property) {
|
|
$apiProperty = new ReflectionProperty($property, self::$generator);
|
|
if (!$this->isDocumented() || $apiProperty->isDocumented()) {
|
|
$this->ownProperties[$property->getName()] = $apiProperty;
|
|
}
|
|
}
|
|
}
|
|
return $this->ownProperties;
|
|
}
|
|
|
|
/**
|
|
* Returns visible properties magicly declared by inspected class.
|
|
*
|
|
* @return array
|
|
*/
|
|
public function getOwnMagicProperties()
|
|
{
|
|
if (null === $this->ownMagicProperties) {
|
|
$this->ownMagicProperties = array();
|
|
|
|
if (!(self::$propertyAccessLevels & InternalReflectionProperty::IS_PUBLIC) || false === $this->getDocComment()) {
|
|
return $this->ownMagicProperties;
|
|
}
|
|
|
|
foreach (array('property', 'property-read', 'property-write') as $annotationName) {
|
|
$annotations = $this->getAnnotation($annotationName);
|
|
if (null === $annotations) {
|
|
continue;
|
|
}
|
|
|
|
foreach ($annotations as $annotation) {
|
|
if (!preg_match('~^(?:([\\w\\\\]+(?:\\|[\\w\\\\]+)*)\\s+)?\\$(\\w+)(?:\\s+(.*))?($)~s', $annotation, $matches)) {
|
|
// Wrong annotation format
|
|
continue;
|
|
}
|
|
|
|
list(, $typeHint, $name, $shortDescription) = $matches;
|
|
|
|
if (empty($typeHint)) {
|
|
$typeHint = 'mixed';
|
|
}
|
|
|
|
$doc = $this->getDocComment();
|
|
$tmp = $annotation;
|
|
if ($delimiter = strpos($annotation, "\n")) {
|
|
$tmp = substr($annotation, 0, $delimiter);
|
|
}
|
|
|
|
$startLine = $this->getStartLine() + substr_count(substr($doc, 0, strpos($doc, $tmp)), "\n");
|
|
$endLine = $startLine + substr_count($annotation, "\n");
|
|
|
|
$magicProperty = new ReflectionPropertyMagic(null, self::$generator);
|
|
$magicProperty
|
|
->setName($name)
|
|
->setTypeHint($typeHint)
|
|
->setShortDescription(str_replace("\n", ' ', $shortDescription))
|
|
->setStartLine($startLine)
|
|
->setEndLine($endLine)
|
|
->setReadOnly('property-read' === $annotationName)
|
|
->setWriteOnly('property-write' === $annotationName)
|
|
->setDeclaringClass($this)
|
|
->addAnnotation('var', $typeHint);
|
|
|
|
$this->ownMagicProperties[$name] = $magicProperty;
|
|
}
|
|
}
|
|
}
|
|
|
|
return $this->ownMagicProperties;
|
|
}
|
|
|
|
/**
|
|
* Returns visible properties declared by traits.
|
|
*
|
|
* @return array
|
|
*/
|
|
public function getTraitProperties()
|
|
{
|
|
$properties = array();
|
|
foreach ($this->reflection->getTraitProperties(self::$propertyAccessLevels) as $property) {
|
|
$apiProperty = new ReflectionProperty($property, self::$generator);
|
|
if (!$this->isDocumented() || $apiProperty->isDocumented()) {
|
|
$properties[$property->getName()] = $apiProperty;
|
|
}
|
|
}
|
|
return $properties;
|
|
}
|
|
|
|
/**
|
|
* Returns a method property.
|
|
*
|
|
* @param string $name Method name
|
|
* @return \ApiGen\ReflectionProperty
|
|
* @throws \InvalidArgumentException If required property does not exist.
|
|
*/
|
|
public function getProperty($name)
|
|
{
|
|
if ($this->hasProperty($name)) {
|
|
return $this->properties[$name];
|
|
}
|
|
|
|
throw new InvalidArgumentException(sprintf('Property %s does not exist in class %s', $name, $this->reflection->getName()));
|
|
}
|
|
|
|
/**
|
|
* Returns visible properties.
|
|
*
|
|
* @return array
|
|
*/
|
|
public function getConstants()
|
|
{
|
|
if (null === $this->constants) {
|
|
$this->constants = array();
|
|
foreach ($this->reflection->getConstantReflections() as $constant) {
|
|
$apiConstant = new ReflectionConstant($constant, self::$generator);
|
|
if (!$this->isDocumented() || $apiConstant->isDocumented()) {
|
|
$this->constants[$constant->getName()] = $apiConstant;
|
|
}
|
|
}
|
|
}
|
|
|
|
return $this->constants;
|
|
}
|
|
|
|
/**
|
|
* Returns constants declared by inspected class.
|
|
*
|
|
* @return array
|
|
*/
|
|
public function getOwnConstants()
|
|
{
|
|
if (null === $this->ownConstants) {
|
|
$this->ownConstants = array();
|
|
$className = $this->reflection->getName();
|
|
foreach ($this->getConstants() as $constantName => $constant) {
|
|
if ($className === $constant->getDeclaringClassName()) {
|
|
$this->ownConstants[$constantName] = $constant;
|
|
}
|
|
}
|
|
}
|
|
return $this->ownConstants;
|
|
}
|
|
|
|
/**
|
|
* Returns a constant reflection.
|
|
*
|
|
* @param string $name Constant name
|
|
* @return \ApiGen\ReflectionConstant
|
|
* @throws \InvalidArgumentException If required constant does not exist.
|
|
*/
|
|
public function getConstantReflection($name)
|
|
{
|
|
if (null === $this->constants) {
|
|
$this->getConstants();
|
|
}
|
|
|
|
if (isset($this->constants[$name])) {
|
|
return $this->constants[$name];
|
|
}
|
|
|
|
throw new InvalidArgumentException(sprintf('Constant %s does not exist in class %s', $name, $this->reflection->getName()));
|
|
}
|
|
|
|
/**
|
|
* Returns a constant reflection.
|
|
*
|
|
* @param string $name Constant name
|
|
* @return \ApiGen\ReflectionConstant
|
|
*/
|
|
public function getConstant($name)
|
|
{
|
|
return $this->getConstantReflection($name);
|
|
}
|
|
|
|
/**
|
|
* Checks if there is a constant of the given name.
|
|
*
|
|
* @param string $constantName Constant name
|
|
* @return boolean
|
|
*/
|
|
public function hasConstant($constantName)
|
|
{
|
|
if (null === $this->constants) {
|
|
$this->getConstants();
|
|
}
|
|
|
|
return isset($this->constants[$constantName]);
|
|
}
|
|
|
|
/**
|
|
* Checks if there is a constant of the given name.
|
|
*
|
|
* @param string $constantName Constant name
|
|
* @return boolean
|
|
*/
|
|
public function hasOwnConstant($constantName)
|
|
{
|
|
if (null === $this->ownConstants) {
|
|
$this->getOwnConstants();
|
|
}
|
|
|
|
return isset($this->ownConstants[$constantName]);
|
|
}
|
|
|
|
/**
|
|
* Returns a constant reflection.
|
|
*
|
|
* @param string $name Constant name
|
|
* @return \ApiGen\ReflectionConstant
|
|
* @throws \InvalidArgumentException If required constant does not exist.
|
|
*/
|
|
public function getOwnConstantReflection($name)
|
|
{
|
|
if (null === $this->ownConstants) {
|
|
$this->getOwnConstants();
|
|
}
|
|
|
|
if (isset($this->ownConstants[$name])) {
|
|
return $this->ownConstants[$name];
|
|
}
|
|
|
|
throw new InvalidArgumentException(sprintf('Constant %s does not exist in class %s', $name, $this->reflection->getName()));
|
|
}
|
|
|
|
/**
|
|
* Returns a constant reflection.
|
|
*
|
|
* @param string $name Constant name
|
|
* @return \ApiGen\ReflectionConstant
|
|
*/
|
|
public function getOwnConstant($name)
|
|
{
|
|
return $this->getOwnConstantReflection($name);
|
|
}
|
|
|
|
/**
|
|
* Returns a parent class reflection encapsulated by this class.
|
|
*
|
|
* @return \ApiGen\ReflectionClass
|
|
*/
|
|
public function getParentClass()
|
|
{
|
|
if ($className = $this->reflection->getParentClassName()) {
|
|
return self::$parsedClasses[$className];
|
|
}
|
|
return $className;
|
|
}
|
|
|
|
/**
|
|
* Returns the parent class name.
|
|
*
|
|
* @return string|null
|
|
*/
|
|
public function getParentClassName()
|
|
{
|
|
return $this->reflection->getParentClassName();
|
|
}
|
|
|
|
/**
|
|
* Returns all parent classes reflections encapsulated by this class.
|
|
*
|
|
* @return array
|
|
*/
|
|
public function getParentClasses()
|
|
{
|
|
if (null === $this->parentClasses) {
|
|
$classes = self::$parsedClasses;
|
|
$this->parentClasses = array_map(function(IReflectionClass $class) use ($classes) {
|
|
return $classes[$class->getName()];
|
|
}, $this->reflection->getParentClasses());
|
|
}
|
|
return $this->parentClasses;
|
|
}
|
|
|
|
|
|
/**
|
|
* Returns the parent classes names.
|
|
*
|
|
* @return array
|
|
*/
|
|
public function getParentClassNameList()
|
|
{
|
|
return $this->reflection->getParentClassNameList();
|
|
}
|
|
|
|
/**
|
|
* Returns if the class implements the given interface.
|
|
*
|
|
* @param string|object $interface Interface name or reflection object
|
|
* @return boolean
|
|
*/
|
|
public function implementsInterface($interface)
|
|
{
|
|
return $this->reflection->implementsInterface($interface);
|
|
}
|
|
|
|
/**
|
|
* Returns all interface reflections encapsulated by this class.
|
|
*
|
|
* @return array
|
|
*/
|
|
public function getInterfaces()
|
|
{
|
|
$classes = self::$parsedClasses;
|
|
return array_map(function(IReflectionClass $class) use ($classes) {
|
|
return $classes[$class->getName()];
|
|
}, $this->reflection->getInterfaces());
|
|
}
|
|
|
|
/**
|
|
* Returns interface names.
|
|
*
|
|
* @return array
|
|
*/
|
|
public function getInterfaceNames()
|
|
{
|
|
return $this->reflection->getInterfaceNames();
|
|
}
|
|
|
|
/**
|
|
* Returns all interfaces implemented by the inspected class and not its parents.
|
|
*
|
|
* @return array
|
|
*/
|
|
public function getOwnInterfaces()
|
|
{
|
|
$classes = self::$parsedClasses;
|
|
return array_map(function(IReflectionClass $class) use ($classes) {
|
|
return $classes[$class->getName()];
|
|
}, $this->reflection->getOwnInterfaces());
|
|
}
|
|
|
|
/**
|
|
* Returns names of interfaces implemented by this class, not its parents.
|
|
*
|
|
* @return array
|
|
*/
|
|
public function getOwnInterfaceNames()
|
|
{
|
|
return $this->reflection->getOwnInterfaceNames();
|
|
}
|
|
|
|
/**
|
|
* Returns all traits reflections encapsulated by this class.
|
|
*
|
|
* @return array
|
|
*/
|
|
public function getTraits()
|
|
{
|
|
$classes = self::$parsedClasses;
|
|
return array_map(function(IReflectionClass $class) use ($classes) {
|
|
return $classes[$class->getName()];
|
|
}, $this->reflection->getTraits());
|
|
}
|
|
|
|
/**
|
|
* Returns names of used traits.
|
|
*
|
|
* @return array
|
|
*/
|
|
public function getTraitNames()
|
|
{
|
|
return $this->reflection->getTraitNames();
|
|
}
|
|
|
|
/**
|
|
* Returns names of traits used by this class an not its parents.
|
|
*
|
|
* @return array
|
|
*/
|
|
public function getOwnTraitNames()
|
|
{
|
|
return $this->reflection->getOwnTraitNames();
|
|
}
|
|
|
|
/**
|
|
* Returns method aliases from traits.
|
|
*
|
|
* @return array
|
|
*/
|
|
public function getTraitAliases()
|
|
{
|
|
return $this->reflection->getTraitAliases();
|
|
}
|
|
|
|
/**
|
|
* Returns all traits used by the inspected class and not its parents.
|
|
*
|
|
* @return array
|
|
*/
|
|
public function getOwnTraits()
|
|
{
|
|
$classes = self::$parsedClasses;
|
|
return array_map(function(IReflectionClass $class) use ($classes) {
|
|
return $classes[$class->getName()];
|
|
}, $this->reflection->getOwnTraits());
|
|
}
|
|
|
|
/**
|
|
* Returns if the class is a trait.
|
|
*
|
|
* @return boolean
|
|
*/
|
|
public function isTrait()
|
|
{
|
|
return $this->reflection->isTrait();
|
|
}
|
|
|
|
/**
|
|
* Returns if the class uses a particular trait.
|
|
*
|
|
* @param string $trait Trait name
|
|
* @return boolean
|
|
*/
|
|
public function usesTrait($trait)
|
|
{
|
|
return $this->reflection->usesTrait($trait);
|
|
}
|
|
|
|
/**
|
|
* Returns reflections of direct subclasses.
|
|
*
|
|
* @return array
|
|
*/
|
|
public function getDirectSubClasses()
|
|
{
|
|
$subClasses = array();
|
|
$name = $this->reflection->getName();
|
|
foreach (self::$parsedClasses as $class) {
|
|
if (!$class->isDocumented()) {
|
|
continue;
|
|
}
|
|
if ($name === $class->getParentClassName()) {
|
|
$subClasses[] = $class;
|
|
}
|
|
}
|
|
return $subClasses;
|
|
}
|
|
|
|
/**
|
|
* Returns reflections of indirect subclasses.
|
|
*
|
|
* @return array
|
|
*/
|
|
public function getIndirectSubClasses()
|
|
{
|
|
$subClasses = array();
|
|
$name = $this->reflection->getName();
|
|
foreach (self::$parsedClasses as $class) {
|
|
if (!$class->isDocumented()) {
|
|
continue;
|
|
}
|
|
if ($name !== $class->getParentClassName() && $class->isSubclassOf($name)) {
|
|
$subClasses[] = $class;
|
|
}
|
|
}
|
|
return $subClasses;
|
|
}
|
|
|
|
/**
|
|
* Returns reflections of classes directly implementing this interface.
|
|
*
|
|
* @return array
|
|
*/
|
|
public function getDirectImplementers()
|
|
{
|
|
if (!$this->isInterface()) {
|
|
return array();
|
|
}
|
|
|
|
$implementers = array();
|
|
$name = $this->reflection->getName();
|
|
foreach (self::$parsedClasses as $class) {
|
|
if (!$class->isDocumented()) {
|
|
continue;
|
|
}
|
|
if (in_array($name, $class->getOwnInterfaceNames())) {
|
|
$implementers[] = $class;
|
|
}
|
|
}
|
|
return $implementers;
|
|
}
|
|
|
|
/**
|
|
* Returns reflections of classes indirectly implementing this interface.
|
|
*
|
|
* @return array
|
|
*/
|
|
public function getIndirectImplementers()
|
|
{
|
|
if (!$this->isInterface()) {
|
|
return array();
|
|
}
|
|
|
|
$implementers = array();
|
|
$name = $this->reflection->getName();
|
|
foreach (self::$parsedClasses as $class) {
|
|
if (!$class->isDocumented()) {
|
|
continue;
|
|
}
|
|
if ($class->implementsInterface($name) && !in_array($name, $class->getOwnInterfaceNames())) {
|
|
$implementers[] = $class;
|
|
}
|
|
}
|
|
return $implementers;
|
|
}
|
|
|
|
/**
|
|
* Returns reflections of classes directly using this trait.
|
|
*
|
|
* @return array
|
|
*/
|
|
public function getDirectUsers()
|
|
{
|
|
if (!$this->isTrait()) {
|
|
return array();
|
|
}
|
|
|
|
$users = array();
|
|
$name = $this->reflection->getName();
|
|
foreach (self::$parsedClasses as $class) {
|
|
if (!$class->isDocumented()) {
|
|
continue;
|
|
}
|
|
|
|
if (in_array($name, $class->getOwnTraitNames())) {
|
|
$users[] = $class;
|
|
}
|
|
}
|
|
return $users;
|
|
}
|
|
|
|
/**
|
|
* Returns reflections of classes indirectly using this trait.
|
|
*
|
|
* @return array
|
|
*/
|
|
public function getIndirectUsers()
|
|
{
|
|
if (!$this->isTrait()) {
|
|
return array();
|
|
}
|
|
|
|
$users = array();
|
|
$name = $this->reflection->getName();
|
|
foreach (self::$parsedClasses as $class) {
|
|
if (!$class->isDocumented()) {
|
|
continue;
|
|
}
|
|
if ($class->usesTrait($name) && !in_array($name, $class->getOwnTraitNames())) {
|
|
$users[] = $class;
|
|
}
|
|
}
|
|
return $users;
|
|
}
|
|
|
|
/**
|
|
* Returns an array of inherited methods from parent classes grouped by the declaring class name.
|
|
*
|
|
* @return array
|
|
*/
|
|
public function getInheritedMethods()
|
|
{
|
|
$methods = array();
|
|
$allMethods = array_flip(array_map(function($method) {
|
|
return $method->getName();
|
|
}, $this->getOwnMethods()));
|
|
|
|
foreach (array_merge($this->getParentClasses(), $this->getInterfaces()) as $class) {
|
|
$inheritedMethods = array();
|
|
foreach ($class->getOwnMethods() as $method) {
|
|
if (!array_key_exists($method->getName(), $allMethods) && !$method->isPrivate()) {
|
|
$inheritedMethods[$method->getName()] = $method;
|
|
$allMethods[$method->getName()] = null;
|
|
}
|
|
}
|
|
|
|
if (!empty($inheritedMethods)) {
|
|
ksort($inheritedMethods);
|
|
$methods[$class->getName()] = array_values($inheritedMethods);
|
|
}
|
|
}
|
|
|
|
return $methods;
|
|
}
|
|
|
|
/**
|
|
* Returns an array of inherited magic methods from parent classes grouped by the declaring class name.
|
|
*
|
|
* @return array
|
|
*/
|
|
public function getInheritedMagicMethods()
|
|
{
|
|
$methods = array();
|
|
$allMethods = array_flip(array_map(function($method) {
|
|
return $method->getName();
|
|
}, $this->getOwnMagicMethods()));
|
|
|
|
foreach (array_merge($this->getParentClasses(), $this->getInterfaces()) as $class) {
|
|
$inheritedMethods = array();
|
|
foreach ($class->getOwnMagicMethods() as $method) {
|
|
if (!array_key_exists($method->getName(), $allMethods)) {
|
|
$inheritedMethods[$method->getName()] = $method;
|
|
$allMethods[$method->getName()] = null;
|
|
}
|
|
}
|
|
|
|
if (!empty($inheritedMethods)) {
|
|
ksort($inheritedMethods);
|
|
$methods[$class->getName()] = array_values($inheritedMethods);
|
|
}
|
|
}
|
|
|
|
return $methods;
|
|
}
|
|
|
|
/**
|
|
* Returns an array of used methods from used traits grouped by the declaring trait name.
|
|
*
|
|
* @return array
|
|
*/
|
|
public function getUsedMethods()
|
|
{
|
|
$usedMethods = array();
|
|
foreach ($this->getMethods() as $method) {
|
|
if (null === $method->getDeclaringTraitName() || $this->getName() === $method->getDeclaringTraitName()) {
|
|
continue;
|
|
}
|
|
|
|
$usedMethods[$method->getDeclaringTraitName()][$method->getName()]['method'] = $method;
|
|
if (null !== $method->getOriginalName() && $method->getName() !== $method->getOriginalName()) {
|
|
$usedMethods[$method->getDeclaringTraitName()][$method->getName()]['aliases'][$method->getName()] = $method;
|
|
}
|
|
}
|
|
|
|
// Sort
|
|
array_walk($usedMethods, function(&$methods) {
|
|
ksort($methods);
|
|
array_walk($methods, function(&$aliasedMethods) {
|
|
if (!isset($aliasedMethods['aliases'])) {
|
|
$aliasedMethods['aliases'] = array();
|
|
}
|
|
ksort($aliasedMethods['aliases']);
|
|
});
|
|
});
|
|
|
|
return $usedMethods;
|
|
}
|
|
|
|
/**
|
|
* Returns an array of used magic methods from used traits grouped by the declaring trait name.
|
|
*
|
|
* @return array
|
|
*/
|
|
public function getUsedMagicMethods()
|
|
{
|
|
$usedMethods = array();
|
|
|
|
foreach ($this->getMagicMethods() as $method) {
|
|
if (null === $method->getDeclaringTraitName() || $this->getName() === $method->getDeclaringTraitName()) {
|
|
continue;
|
|
}
|
|
|
|
$usedMethods[$method->getDeclaringTraitName()][$method->getName()]['method'] = $method;
|
|
}
|
|
|
|
// Sort
|
|
array_walk($usedMethods, function(&$methods) {
|
|
ksort($methods);
|
|
array_walk($methods, function(&$aliasedMethods) {
|
|
if (!isset($aliasedMethods['aliases'])) {
|
|
$aliasedMethods['aliases'] = array();
|
|
}
|
|
ksort($aliasedMethods['aliases']);
|
|
});
|
|
});
|
|
|
|
return $usedMethods;
|
|
}
|
|
|
|
/**
|
|
* Returns an array of inherited constants from parent classes grouped by the declaring class name.
|
|
*
|
|
* @return array
|
|
*/
|
|
public function getInheritedConstants()
|
|
{
|
|
return array_filter(
|
|
array_map(
|
|
function(ReflectionClass $class) {
|
|
$reflections = $class->getOwnConstants();
|
|
ksort($reflections);
|
|
return $reflections;
|
|
},
|
|
array_merge($this->getParentClasses(), $this->getInterfaces())
|
|
)
|
|
);
|
|
}
|
|
|
|
/**
|
|
* Returns an array of inherited properties from parent classes grouped by the declaring class name.
|
|
*
|
|
* @return array
|
|
*/
|
|
public function getInheritedProperties()
|
|
{
|
|
$properties = array();
|
|
$allProperties = array_flip(array_map(function($property) {
|
|
return $property->getName();
|
|
}, $this->getOwnProperties()));
|
|
|
|
foreach ($this->getParentClasses() as $class) {
|
|
$inheritedProperties = array();
|
|
foreach ($class->getOwnProperties() as $property) {
|
|
if (!array_key_exists($property->getName(), $allProperties) && !$property->isPrivate()) {
|
|
$inheritedProperties[$property->getName()] = $property;
|
|
$allProperties[$property->getName()] = null;
|
|
}
|
|
}
|
|
|
|
if (!empty($inheritedProperties)) {
|
|
ksort($inheritedProperties);
|
|
$properties[$class->getName()] = array_values($inheritedProperties);
|
|
}
|
|
}
|
|
|
|
return $properties;
|
|
}
|
|
|
|
/**
|
|
* Returns an array of inherited magic properties from parent classes grouped by the declaring class name.
|
|
*
|
|
* @return array
|
|
*/
|
|
public function getInheritedMagicProperties()
|
|
{
|
|
$properties = array();
|
|
$allProperties = array_flip(array_map(function($property) {
|
|
return $property->getName();
|
|
}, $this->getOwnMagicProperties()));
|
|
|
|
foreach ($this->getParentClasses() as $class) {
|
|
$inheritedProperties = array();
|
|
foreach ($class->getOwnMagicProperties() as $property) {
|
|
if (!array_key_exists($property->getName(), $allProperties)) {
|
|
$inheritedProperties[$property->getName()] = $property;
|
|
$allProperties[$property->getName()] = null;
|
|
}
|
|
}
|
|
|
|
if (!empty($inheritedProperties)) {
|
|
ksort($inheritedProperties);
|
|
$properties[$class->getName()] = array_values($inheritedProperties);
|
|
}
|
|
}
|
|
|
|
return $properties;
|
|
}
|
|
|
|
/**
|
|
* Returns an array of used properties from used traits grouped by the declaring trait name.
|
|
*
|
|
* @return array
|
|
*/
|
|
public function getUsedProperties()
|
|
{
|
|
$properties = array();
|
|
$allProperties = array_flip(array_map(function($property) {
|
|
return $property->getName();
|
|
}, $this->getOwnProperties()));
|
|
|
|
foreach ($this->getTraits() as $trait) {
|
|
$usedProperties = array();
|
|
foreach ($trait->getOwnProperties() as $property) {
|
|
if (!array_key_exists($property->getName(), $allProperties)) {
|
|
$usedProperties[$property->getName()] = $property;
|
|
$allProperties[$property->getName()] = null;
|
|
}
|
|
}
|
|
|
|
if (!empty($usedProperties)) {
|
|
ksort($usedProperties);
|
|
$properties[$trait->getName()] = array_values($usedProperties);
|
|
}
|
|
}
|
|
|
|
return $properties;
|
|
}
|
|
|
|
/**
|
|
* Returns an array of used magic properties from used traits grouped by the declaring trait name.
|
|
*
|
|
* @return array
|
|
*/
|
|
public function getUsedMagicProperties()
|
|
{
|
|
$properties = array();
|
|
$allProperties = array_flip(array_map(function($property) {
|
|
return $property->getName();
|
|
}, $this->getOwnMagicProperties()));
|
|
|
|
foreach ($this->getTraits() as $trait) {
|
|
$usedProperties = array();
|
|
foreach ($trait->getOwnMagicProperties() as $property) {
|
|
if (!array_key_exists($property->getName(), $allProperties)) {
|
|
$usedProperties[$property->getName()] = $property;
|
|
$allProperties[$property->getName()] = null;
|
|
}
|
|
}
|
|
|
|
if (!empty($usedProperties)) {
|
|
ksort($usedProperties);
|
|
$properties[$trait->getName()] = array_values($usedProperties);
|
|
}
|
|
}
|
|
|
|
return $properties;
|
|
}
|
|
|
|
/**
|
|
* Checks if there is a property of the given name.
|
|
*
|
|
* @param string $propertyName Property name
|
|
* @return boolean
|
|
*/
|
|
public function hasProperty($propertyName)
|
|
{
|
|
if (null === $this->properties) {
|
|
$this->getProperties();
|
|
}
|
|
|
|
return isset($this->properties[$propertyName]);
|
|
}
|
|
|
|
/**
|
|
* Checks if there is a property of the given name.
|
|
*
|
|
* @param string $propertyName Property name
|
|
* @return boolean
|
|
*/
|
|
public function hasOwnProperty($propertyName)
|
|
{
|
|
if (null === $this->ownProperties) {
|
|
$this->getOwnProperties();
|
|
}
|
|
|
|
return isset($this->ownProperties[$propertyName]);
|
|
}
|
|
|
|
/**
|
|
* Checks if there is a property of the given name.
|
|
*
|
|
* @param string $propertyName Property name
|
|
* @return boolean
|
|
*/
|
|
public function hasTraitProperty($propertyName)
|
|
{
|
|
$properties = $this->getTraitProperties();
|
|
return isset($properties[$propertyName]);
|
|
}
|
|
|
|
/**
|
|
* Checks if there is a method of the given name.
|
|
*
|
|
* @param string $methodName Method name
|
|
* @return boolean
|
|
*/
|
|
public function hasMethod($methodName)
|
|
{
|
|
if (null === $this->methods) {
|
|
$this->getMethods();
|
|
}
|
|
|
|
return isset($this->methods[$methodName]);
|
|
}
|
|
|
|
/**
|
|
* Checks if there is a method of the given name.
|
|
*
|
|
* @param string $methodName Method name
|
|
* @return boolean
|
|
*/
|
|
public function hasOwnMethod($methodName)
|
|
{
|
|
if (null === $this->ownMethods) {
|
|
$this->getOwnMethods();
|
|
}
|
|
|
|
return isset($this->ownMethods[$methodName]);
|
|
}
|
|
|
|
/**
|
|
* Checks if there is a method of the given name.
|
|
*
|
|
* @param string $methodName Method name
|
|
* @return boolean
|
|
*/
|
|
public function hasTraitMethod($methodName)
|
|
{
|
|
$methods = $this->getTraitMethods();
|
|
return isset($methods[$methodName]);
|
|
}
|
|
|
|
/**
|
|
* Returns if the class is valid.
|
|
*
|
|
* @return boolean
|
|
*/
|
|
public function isValid()
|
|
{
|
|
if ($this->reflection instanceof TokenReflection\Invalid\ReflectionClass) {
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* Returns if the class should be documented.
|
|
*
|
|
* @return boolean
|
|
*/
|
|
public function isDocumented()
|
|
{
|
|
if (null === $this->isDocumented && parent::isDocumented()) {
|
|
$fileName = self::$generator->unPharPath($this->reflection->getFilename());
|
|
foreach (self::$config->skipDocPath as $mask) {
|
|
if (fnmatch($mask, $fileName, FNM_NOESCAPE)) {
|
|
$this->isDocumented = false;
|
|
break;
|
|
}
|
|
}
|
|
if (true === $this->isDocumented) {
|
|
foreach (self::$config->skipDocPrefix as $prefix) {
|
|
if (0 === strpos($this->reflection->getName(), $prefix)) {
|
|
$this->isDocumented = false;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return $this->isDocumented;
|
|
}
|
|
}
|