Finds all parent classes of the given class

@param ClassReflection $class The class to reflect
@param array $parentClasses Array of parent classes
@return array<ClassReflection>
506982
protected function getParentClasses(ClassReflection $class, array $parentClasses = [])
    {
        $parentClass = $class->getParentClass();
        if ($parentClass !== false) {
            $parentClasses[] = $parentClass;
            $parentClasses = $this->getParentClasses($parentClass, $parentClasses);
        }

        return $parentClasses;
    }
165499
protected static function _generateAbstractMethods($class)
    {
        $result = [];
        if (!class_exists($class)) {
            throw new MissingImplementationException("Unexisting parent class `{$class}`");
        }
        $reflection = Inspector::inspect($class);
        $methods = $reflection->getMethods(ReflectionMethod::IS_ABSTRACT);
        foreach ($methods as $method) {
            $result[$method->getName()] = static::_generateMethod($method);
        }
        return $result;
    }
953744
public function getParentByClass($cls)
    {
        if (!is_array($cls)) $cls = array($cls);
        $d = $this;
        while ($d) {
            foreach ($cls as $i) {
                if (is_instance_of($d->componentClass, $i)) {
                    return $d;
                }
            }
            $d = $d->parent;
        }
        return $d;
    }
1047760
protected function classUsesDeep($class)
    {
        $traits = [];

        // Get traits of all parent classes
        do {
            $traits = array_merge(class_uses($class), $traits);
        } while ($class = get_parent_class($class));

        // Get traits of all parent traits
        $traitsToSearch = $traits;
        while ( ! empty($traitsToSearch)) {
            $newTraits      = class_uses(array_pop($traitsToSearch));
            $traits         = array_merge($newTraits, $traits);
            $traitsToSearch = array_merge($newTraits, $traitsToSearch);
        };

        foreach ($traits as $trait => $same) {
            $traits = array_merge(class_uses($trait), $traits);
        }

        return array_unique($traits);
    }
892573
public function getImplements($class)
    {
        $interfaces = [];
        $classId = $this->getClassId($class);
        if (isset($classId)) {
            if (isset($this->implements[$classId])) {
                foreach ($this->implements[$classId] as $interfaceId) {
                    $interfaces[$this->interfaces[$interfaceId]] = 1;
                }
            }
            foreach ($this->getAncestors($class) as $parent) {
                foreach ($this->getImplements($parent) as $interface) {
                    $interfaces[$interface] = 1;
                }
            }
        }
        return array_keys($interfaces);
    }
1234639
private function getChildEvents(string $eventClass, iterable $eventClasses): iterable
    {
        $reflection = new ReflectionClass($eventClass);
        foreach ($eventClasses as $curEventClass) {
            $curReflection = new ReflectionClass($curEventClass);
            if ($curReflection->isAbstract() === false) {
                if ($eventClass === $curEventClass ||
                    $curReflection->isSubclassOf($eventClass) === true ||
                    ($reflection->isInterface() === true && $curReflection->implementsInterface($eventClass))
                ) {
                    yield $curEventClass;
                }
            }
        }
    }
1084688
public function getParentClass()
    {
        $parentClass  = parent::getParentClass();
        if (null === $parentClass || false === $parentClass) {
            return null;
        }
        
        $moufRefClass = new self($parentClass->getName());
        return $moufRefClass;
    }
46542
protected function givenClassAndParentTraits($class, $autoload = true)
    {
        $traits = [];

        // Get traits of all parent classes
        while ($class = get_parent_class($class)) {
            $traits = array_merge(class_uses($class, $autoload), $traits);
        };

        // Get traits of all parent traits
        $traitsToSearch = $traits;
        while ( ! empty($traitsToSearch)) {
            $newTraits = class_uses(array_pop($traitsToSearch), $autoload);
            $traits = array_merge($newTraits, $traits);
            $traitsToSearch = array_merge($newTraits, $traitsToSearch);
        };

        foreach ($traits as $trait => $same) {
            $traits = array_merge(class_uses($trait, $autoload), $traits);
        }

        return array_unique($traits);
    }
476683
protected static function selectClassExtends(array $classes, string $parentClass): iterable
    {
        foreach ($classes as $className) {
            if (static::classExtends($className, $parentClass) === true) {
                yield $className;
            }
        }
    }
760448
public function getClass()
    {
        try {
            $class = parent::getClass();
        } catch (\Exception $exception) {
            return null;
        }

        return is_object($class) ? new ClassReflection($class->getName()) : null;
    }
744079
private static function getProperties($class): array
    {
        $reflect = new \ReflectionClass($class);
        $prop = $reflect->getProperties(
            \ReflectionProperty::IS_PUBLIC | \ReflectionProperty::IS_PROTECTED | \ReflectionProperty::IS_PRIVATE
        );
        $properties = [];
        foreach ($prop as $property) {
            $properties[] = $property->name;
        }
        $parent = \get_parent_class($class);
        if ($parent) {
            $properties = \array_merge(self::getProperties($parent), $properties);
        }
        return $properties;
    }
1323713
protected static function __classSort(ClassReflection $a, ClassReflection $b)
    {
        if ($a->getSort() > $b->getSort()) {
            return -1;
        }
        if ($a->getSort() < $b->getSort()) {
            return 1;
        }
        return 0;
    }
435534
private function getHierarchyClasses($className)
    {
        $classes         = [];
        $parentClassName = $className;

        while ($parentClassName && $currentClass = $this->reflectionService->getClass($parentClassName)) {
            $classes[]       = $currentClass;
            $parentClassName = null;

            if ($parentClass = $currentClass->getParentClass()) {
                $parentClassName = $parentClass->getName();
            }
        }

        return $classes;
    }
422888
public function getDescendantsOf($class)
    {
        if (is_object($class)) {
            $class = get_class($class);
        }

        $lClass = strtolower($class);
        if (array_key_exists($lClass, $this->descendants)) {
            return $this->descendants[$lClass];
        }

        return [];
    }
1300925
private static function getMethods($methods, $class): array
    {
        $methods[] = \array_fill_keys(\get_class_methods($class), 0);
        $parent = \get_parent_class($class);
        if ($parent) {
            \array_merge($methods, self::getMethods($methods, $parent));
        }
        return $methods[0];
    }
606807
public static function getAllProperties($class, $blacklist = [])
    {
        $classReflection = new \ReflectionClass($class);

        $properties = $classReflection->getProperties();

        if ($parentClass = $classReflection->getParentClass()) {
            $parentProps = self::getAllProperties($parentClass->getName(), $blacklist);
            if (!empty($parentProps)) {
                $properties = array_merge($parentProps, $properties);
            }
        }
        if (empty($blacklist)) {
            return $properties;
        }

        return array_filter(
            $properties,
            function (\ReflectionProperty $property) use ($blacklist) {
                return !$property->isStatic() && !in_array($property->name, $blacklist);
            }
        );
    }
316705
public static function fromMethod(
        string $method,
        string $class = null,
        bool $withParents = false
    ): array
    {
        if ($class) {

            try {

                $refMethod = new \ReflectionMethod($class, $method);
            }
            catch (\ReflectionException $e) {

                throw new Exception(
                    "Method '{$class}::{$method}' not found.",
                    Exception::METHOD_NOT_FOUND
                );
            }
        }
        else {

            try {

                $refMethod = new \ReflectionMethod($method);
            }
            catch (\ReflectionException $e) {

                throw new Exception(
                    "Method '{$method}' not found.",
                    Exception::METHOD_NOT_FOUND
                );
            }
        }

        $docComment = $refMethod->getDocComment();

        if ($withParents) {

            $refClass = $refMethod->getDeclaringClass();

            while (1) {

                if ($refClass = $refClass->getParentClass()) {

                    try {

                        $refMethod = $refClass->getMethod($method);
                    }
                    catch (\ReflectionException $e) {

                        break;
                    }

                    if (!$refMethod) {

                        continue;
                    }

                    if ($parentDoc = $refMethod->getDocComment()) {

                        $docComment = $docComment === false ?
                            $parentDoc :
                            "{$parentDoc}{$docComment}";
                    }
                }
                else {

                    break;
                }
            }
        }

        unset($refMethod, $refClass);

        if ($docComment === false) {

            return [];
        }

        return Parser::parseDocComment($docComment);
    }