Fetches conditions from all parent method prototypes recursively

@param ReflectionClass $class
@param string          $methodName

@return array
@throws ReflectionException
349468
public function getConditions(ReflectionClass $class, string $methodName): array
    {
        $annotations   = [];
        $parentMethods = [];
        $docComment    = $class->getMethod($methodName)->getDocComment();

        if ($docComment === false) {
            return $annotations;
        }

        if (\preg_match('/\@inheritdoc/i', $docComment)) {
            $this->getParentClassesMethods($class, $methodName, $parentMethods);
            $this->getInterfacesMethods($class, $methodName, $parentMethods);
        }

        foreach ($parentMethods as $parentMethod) {
            $annotations[] = $this->annotationReader->getMethodAnnotations($parentMethod);
        }

        if (\count($annotations)) {
            $annotations = \array_merge(...$annotations);
        }

        return $this->filterContractAnnotation($annotations);
    }
1317229
function getMethod($methodName)
    {
        if (!$this->hasMethod($methodName))
            throw new \Exception(sprintf(
                'Method (%s) not found.'
                , $methodName
            ));

        if (isset($this->_t__methods[$methodName])) {
            ## from bind closure
            $methodCallable = $this->_t__methods[$methodName];
        } else {
            $bindTo = $this->getBindTo();
            $methodCallable = function() use($methodName, $bindTo) {
                return call_user_func_array([$bindTo, $methodName], func_get_args());
            };
        }

        ## bind it into latest bind object
        $methodCallable = \Closure::bind(
            $methodCallable
            , $this->getBindTo()
            , get_class($this->getBindTo())
        );

        return $methodCallable;
    }
189509
private function getMethodInstances($class, $methodName = '__construct')
    {
        if (is_object($class)) {
            $reflectClass = new ReflectionClass(get_class($class));
        } else {
            $reflectClass = new ReflectionClass($class);
        }

        $instances = [];
        $hasDI = false;

        if ($reflectClass->hasMethod($methodName)) {
            $reflectMethod = $reflectClass->getMethod($methodName);

            $params = $reflectMethod->getParameters();

            if (count($params) > 0) {
                foreach ($params as $param) {
                    $paramClass = $param->getClass();
                    if ($paramClass) {
                        $paramClassName = $paramClass->getName();
                        array_push($instances, Container::getByClassName($paramClassName));
                        $hasDI = true;
                    } elseif ($hasDI) {
                        throw new NotFoundException('Dependency Injection cannot work with normal params');
                    }
                }
            }
        }

        if ($hasDI) {
            return $instances;
        }

        return false;
    }
1207889
private static function getProps($class)
    {
        if ($class == NULL) {
            return array();
        }
        $class = new \ReflectionClass($class);
        $properties = array_filter($class->getProperties(), function ($prop) use($class)
        {
            return $prop->getDeclaringClass()->name == $class->name;
        });
        return $properties;
    }
810089
private function getBindParams(string $className, string $methodName, \Throwable $throwable)
    {
        $reflectClass  = new \ReflectionClass($className);
        $reflectMethod = $reflectClass->getMethod($methodName);
        $reflectParams = $reflectMethod->getParameters();
        $response      = RequestContext::getResponse();
        $request       = RequestContext::getRequest();

        // binding params
        $bindParams = [];
        foreach ($reflectParams as $key => $reflectParam) {
            $reflectType = $reflectParam->getType();

            // undefined type of the param
            if ($reflectType === null) {
                $bindParams[$key] = null;
                continue;
            }

            /**
             * defined type of the param
             * @notice \ReflectType::getName() is not supported in PHP 7.0, that is why use __toString()
             */
            $type = $reflectType->__toString();
            if ($type === Request::class) {
                $bindParams[$key] = $request;
            } elseif ($type == Response::class) {
                $bindParams[$key] = $response;
            } elseif ($type == \Throwable::class) {
                $bindParams[$key] = $throwable;
            } else {
                $bindParams[$key] = null;
            }
        }

        return $bindParams;
    }
611996
protected function getMethodArguments($methodName)
    {
        if (!empty($this->_magicMethodArgumentNames)) {
            return ArrayHelper::getValue($this->_magicMethodArgumentNames, $methodName, []);
        }
        try {
            $reflectionClass = new \ReflectionClass($this);
            $comment = $reflectionClass->getDocComment();
            $lines = preg_split('/[\r\n]/', $comment);
            $regexp = '#\s*\*\s*@method ((?:.*) )?([a-zA-Z_]+)\(((?:[\\a-zA-Z]+\s+)?\$(?:[a-zA-Z_]+),?\s*)*\)#';

            foreach ($lines as $line) {
                $matches = [];
                if (preg_match($regexp, $line, $matches)) {
                    @list($null, $returnType, $method, $argumentString) = $matches;
                    if (is_null($argumentString)) {
                        $arguments = [];
                    } else {
                        $arguments = array_map('trim', explode(',', $argumentString));

                        foreach ($arguments as $k => $argument) {
                            if (empty($argument)) {
                                continue;
                            }
                            if (strpos($argument, ' ') !== false) {
                                $tmp = explode(' ', $argument);
                                $arguments[$k] = ['name' => ltrim($tmp[1], '$'), 'type' => $tmp[0]];
                            } else {
                                $arguments[$k] = ['name' => ltrim($argument, '$'), 'type' => 'mixed'];
                            }
                        }
                    }

                    $this->_magicMethodArgumentNames[$method] = $arguments;
                }
            }
        } catch (\ReflectionException $e) {

        }

        return ArrayHelper::getValue($this->_magicMethodArgumentNames, $methodName, []);
    }
222252
private function getParentProperties(\ReflectionClass $reflectionClass)
    {
        $parent = $reflectionClass->getParentClass();
        if ($parent != null) {
            return array_merge($reflectionClass->getProperties(), $this->getParentProperties($parent));
        }

        return $reflectionClass->getProperties();
    }
301824
public function getConditions(ReflectionClass $class): array
    {
        $annotations   = [];
        $parents = [];

        $this->getParentClasses($class, $parents);
        $this->getInterfaces($class, $parents);

        foreach ($parents as $parent) {
            $annotations[] = $this->annotationReader->getClassAnnotations($parent);
        }

        if (\count($annotations)) {
            $annotations = \array_merge(...$annotations);
        }

        return $this->filterContractAnnotation($annotations);
    }
130891
private static function getMethodRequiredClassesByMethod(\ReflectionMethod $rm) : array
    {
        $classes = [];
        
        $params = $rm->getParameters();
        foreach($params as $rp){
            $type = $rp->getType();
            if ($type instanceof \ReflectionType && !$type->isBuiltin()){
                $type_class = "$type";
                $classes[] = new \ReflectionClass($type_class);
            }
        }
        
        $has_return_type = $rm->hasReturnType();
        if ($has_return_type){
            $ret_type = $rm->getReturnType();
            if (!$ret_type->isBuiltin()){
                $ret_type_class = "$ret_type";
                $classes[] = new \ReflectionClass($ret_type_class);
            }
        }
        
        return array_unique($classes);
    }
791130
private function findOnMethods(\ReflectionClass $class, Valid $valid)
    {
        $onValidateMethod = $onFailureMethod = null;
        foreach ($class->getMethods() as $method) {
            $annotations = $this->reader->getMethodAnnotations($method);
            list($onValidateMethod, $onFailureMethod) = $this->scanAnnotation(
                $valid,
                $annotations,
                $method,
                $onValidateMethod,
                $onFailureMethod
            );
        }

        return [$onValidateMethod, $onFailureMethod];
    }
1271758
public static function parseClassMethod($fullClassName, $methodName)
    {
        $class      = self::parseClass($fullClassName);
        $classNodes = $class->stmts;

        foreach ($classNodes as $classLevelNode) {
            if ($classLevelNode instanceof ClassMethod && $classLevelNode->name->toString() == $methodName) {
                return $classLevelNode;
            }
        }

        throw new \InvalidArgumentException("Method $methodName was not found in the $fullClassName");
    }
1145651
public function getTraitProvidingProperty(ReflectionClass $class, string $propertyName): ReflectionClass
    {
        $traitsWithProperty = [];
        foreach ($class->getTraits() as $trait) {
            try {
                $trait->getProperty($propertyName);
                $traitsWithProperty[] = $trait;
            } catch (\ReflectionException $e) {
            }
        }
        if ([] === $traitsWithProperty) {
            if ($class->isTrait() && $class->hasProperty($propertyName)) {
                return $class;
            }
            throw new \RuntimeException(
                'Failed finding trait providing the property ' . $propertyName . ' in ' .
                $class->getShortName()
            );
        }
        if (count($traitsWithProperty) > 1) {
            throw new \RuntimeException(
                'Found more than one trait providing the property ' . $propertyName . ' in ' .
                $class->getShortName()
            );
        }

        return current($traitsWithProperty);
    }
185569
private function extractMethods(\ReflectionClass $objectClass): array
    {
        return methodsOf($objectClass, \ReflectionMethod::IS_PUBLIC)
                ->filter(function(\ReflectionMethod $method)
                        {
                            if ($method->getNumberOfParameters() != 0
                                    || $method->isStatic()
                                    || $method->isConstructor()
                                    || $method->isDestructor()
                                    || 0 == strncmp($method->getName(), '__', 2)) {
                                return false;
                            }

                            return !annotationsOf($method)->contain('XmlIgnore');
                        }
                )->map(function(\ReflectionMethod $method)
                        {
                            return $this->createSerializerDelegate(
                                    annotationsOf($method),
                                    $method->getName()
                            );
                        }

                )->data();
    }
141843
private function getMethodParameters(string $class, string $methodName) : array
    {
        $methodReflection = new ReflectionMethod($class, $methodName);
        $parametersName   = [];

        foreach ($methodReflection->getParameters() as $parameter) {
            $parametersName[] = $parameter->name;
        }

        return $parametersName;
    }
1008728
public function getNumberOfMethodCalls($className, $methodName)
    {
        if (isset($this->methodCalls[$className][$methodName])) {
            return $this->methodCalls[$className][$methodName];
        }

        return 0;
    }
1155811
public static function fromMethodName(string $methodName): array
    {
        if (strpos($methodName, '::') > 0) {
            list($className, $functionName) = explode('::', $methodName);
        } elseif (substr($methodName, -9, 9) === '{closure}') {
            $className = substr($methodName, 0, -9);
            $functionName = '{closure}';
        }

        return [
            'FLOW_LOG_ENVIRONMENT' => [
                'packageKey' => self::getPackageKeyFromClassName($className),
                'className' => $className,
                'methodName' => $functionName
            ]
        ];
    }
477096
protected static function _controllerMethods($className)
    {
        if (!class_exists($className)) {
            return [];
        }

        $methods = (array)get_this_class_methods($className);
        $actions = [];
        foreach ($methods as $methodName) {
            try {
                $method = new ReflectionMethod($className, $methodName);
                if ($method->isPublic()) {
                    $actions[] = $methodName;
                }
            } catch (\ReflectionException $e) {
                // error
            }
        }

        return $actions;
    }