@inheritdoc

@throws ReflectionException
769137
final public function get(array $appConfig): array
    {
        $defaults = $this->getSettings();

        $policiesFolder   = $defaults[static::KEY_POLICIES_FOLDER] ?? null;
        $policiesFileMask = $defaults[static::KEY_POLICIES_FILE_MASK] ?? null;

        assert(
            $policiesFolder !== null && empty(glob($policiesFolder)) === false,
            "Invalid Policies folder `$policiesFolder`."
        );
        assert(empty($policiesFileMask) === false, "Invalid Policies file mask `$policiesFileMask`.");
        $policiesPath = $policiesFolder . DIRECTORY_SEPARATOR . $policiesFileMask;

        $topPolicyName = $defaults[static::KEY_TOP_POLICY_NAME];

        $loader = (new AuthorizationRulesLoader($policiesPath, $topPolicyName));

        return $defaults + [
                static::KEY_POLICIES_DATA => $loader->getRulesData(),
            ];
    }
151136
public function methodDoc(&$methods)
    {
        $this->depth++;
        if ($methods) {
            foreach ($methods as $method) {
                $type = $method->returnType();
                echo $this->showDepth(), '- ', $method->modifiers();
                if ($type) {
                    echo $type->toString(), ' ';
                } else {
                    echo 'void ';
                }
                echo $method->packageName(), '\\', $method->name(), $method->flatSignature();
                echo ' [', $method->location(), ']';
                echo "\n";
                $this->fieldDoc($method->parameters());
                $this->methodDoc($method->functions());
                $exceptions =& $method->thrownExceptions();
                if ($exceptions) {
                    foreach ($exceptions as $exception) {
                        echo $this->showDepth(), '|- throws ';
                        if (is_object($exception)) {
                            echo $exception->packageName(), '\\', $exception->name(), "\n";
                        } else {
                            echo $exception, "\n";
                        }
                    }
                }
                $this->docComment($method);
            }
        }
        $this->depth--;
    }
848208
public function evaluateAnnotation(
        Request $request,
        Annotation $annotation,
        ReflectionMethod $method
    ) {
        /**
         * Annotation is only laoded if is typeof WorkAnnotation.
         */
        if ($annotation instanceof CreateForm) {

            /**
             * Once loaded Annotation info, we just instanced Service name.
             */
            $annotationValue = $annotation->getClass();

            /**
             * Get FormType object given a service name.
             */
            $type = $this
                    ->formRegistry
                    ->getType($annotationValue)
                    ->getInnerType();

            /**
             * Get the parameter name. If not defined, is set as $form.
             */
            $parameterName = $annotation->getName() ?: $this->defaultName;
            $parameterClass = $this->getParameterType(
                $method,
                $parameterName,
                FormInterface::class
            );

            /**
             * Requiring result with calling getBuiltObject(), set as request
             * attribute desired element.
             */
            $request->attributes->set(
                $parameterName,
                $this->getBuiltObject(
                    $request,
                    $this->formFactory,
                    $annotation,
                    $parameterClass,
                    $type
                )
            );
        }
    }
221472
public function process(\ReflectionClass $reflection, Definition $definition)
    {
        $annotations = $this->reader->getClassAnnotations($reflection);

        foreach ($annotations as $annotation)
        {
            if ($annotation instanceof Link) {
                $link = $this->createLink($annotation);

                $definition->addLink($link);
                continue;
            }

            if ($annotation instanceof ResourceIdentifier && $annotation->type !== null) {
                $definition->setType($annotation->type);
            }
        }
    }
1278283
private function completeField(Input $field, ReflectionMethod $method, ReflectionParameter $param): void
    {
        $fieldName = lcfirst(preg_replace('~^set~', '', $method->getName()));
        if (!$field->getName()) {
            $field->setName($fieldName);
        }

        $docBlock = new DocBlockReader($method);
        if (!$field->getDescription()) {
            $field->setDescription($docBlock->getMethodDescription());
        }

        $this->completeFieldDefaultValue($field, $param, $fieldName);
        $this->completeFieldType($field, $method, $param, $docBlock);
    }
459687
private function bindRequestParamsToClass(ServerRequestInterface $request, \ReflectionClass $reflectClass)
    {
        try {
            $object = $reflectClass->newInstance();
            $queryParams = $request->getQueryParams();
            // Get request body, auto decode when content type is json format
            if (StringHelper::startsWith($request->getHeaderLine('Content-Type'), 'application/json')) {
                $requestBody = JsonHelper::decode($request->getBody()->getContents(), true);
            } else {
                $requestBody = $request->getParsedBody();
            }
            // Merge query params and request body
            $requestParams = array_merge($queryParams, $requestBody);
            // Binding request params to target object
            $properties = $reflectClass->getProperties();
            foreach ($properties as $property) {
                $name = $property->getName();
                if (!isset($requestParams[$name])) {
                    continue;
                }
                if (!$property->isPublic()) {
                    $property->setAccessible(true);
                }
                $property->setValue($object, $requestParams[$name]);
            }
        } catch (\Exception $e) {
            $object = null;
        }
        return $object;
    }
6429
final public function resolveArguments(
        ContextFunction $reflection,
        array $parameters = [],
        string $context = null
    ): array {
        $arguments = [];
        foreach ($reflection->getParameters() as $parameter) {
            try {
                //Information we need to know about argument in order to resolve it's value
                $name = $parameter->getName();
                $class = $parameter->getClass();
            } catch (\Throwable $e) {
                //Possibly invalid class definition or syntax error
                throw new ContainerException($e->getMessage(), $e->getCode(), $e);
            }

            if (isset($parameters[$name]) && is_object($parameters[$name])) {
                if ($parameters[$name] instanceof Autowire) {
                    //Supplied by user as late dependency
                    $arguments[] = $parameters[$name]->resolve($this);
                } else {
                    //Supplied by user as object
                    $arguments[] = $parameters[$name];
                }
                continue;
            }

            //No declared type or scalar type or array
            if (empty($class)) {
                //Provided from outside
                if (array_key_exists($name, $parameters)) {
                    //Make sure it's properly typed
                    $this->assertType($parameter, $reflection, $parameters[$name]);
                    $arguments[] = $parameters[$name];
                    continue;
                }

                if ($parameter->isDefaultValueAvailable()) {
                    //Default value
                    $arguments[] = $parameter->getDefaultValue();

                    continue;
                }

                //Unable to resolve scalar argument value
                throw new ArgumentException($parameter, $reflection);
            }

            try {
                //Requesting for contextual dependency
                $arguments[] = $this->get($class->getName(), $name);

                continue;
            } catch (AutowireException $e) {
                if ($parameter->isOptional()) {
                    //This is optional dependency, skip
                    $arguments[] = null;
                    continue;
                }

                throw $e;
            }
        }

        return $arguments;
    }
545456
public function interfaceInjection($reflectionParam)
    {
        $constructorArgs = null;
        /*
         | Check if constructor dependency is Interface or not.
         | if interface we will check definition for the interface
         | and inject into controller constructor
         */
        if (!$reflectionParam->IsInstantiable() && $reflectionParam->isInterface()) {
            $aliases = $this->definition['definition.config']['register.alias'];
            $interface = Inflector::getClassName($reflectionParam->getName());

            if (array_key_exists($interface, $aliases)) {
                $constructorArgs = $this->container->makeInstance($aliases[$interface]);
            }
        }

        return $constructorArgs;
    }
1115933
protected function getRelatedEntityValue($fieldExplode, $entity, \ReflectionClass $reflectionClass)
    {
        $subFieldName = array_shift($fieldExplode);
        $getter = $this->getFieldGetter($reflectionClass, $subFieldName);
        $entities = $getter->invoke($entity);

        $outValues = array();
        foreach ($entities as $entity) {
            $reflectionClass = new \ReflectionClass($entity);
            // The value is a field of a subentity
            foreach ($fieldExplode as $subFieldName) {
                $getter = $this->getFieldGetter($reflectionClass, $subFieldName);
                $outValue = $getter->invoke($entity);

                if ($outValue) {
                    if (is_object($outValue)) {
                        // If there are more subfields to treat this is the next entity
                        $entity = $outValue;
                        $reflectionClass = new \ReflectionClass($entity);
                    }
                }
                else {
                    // We have no value for this field
                    break;
                }
            }
            $outValues[] = $outValue;
        }

        return $outValues;
    }
621778
public function parse($annotation, \ReflectionClass $refClass, Endpoint $endpoint)
    {
        $field = new FieldDefinition();

        if ($annotation->name) {
            $field->setName($annotation->name);
        } else {
            $field->setName(lcfirst(ClassUtils::getDefaultName($refClass->getName())));
        }

        $objectType = null;
        preg_match('/(\w+)\\\\Field\\\\(\w+)$/', $refClass->getName(), $matches);
        if (!isset($matches[1]) || !$endpoint->hasType($matches[1])) {
            $error = sprintf('Can`t resolve a valid object type for field "%s"', $refClass->getName());
            throw new \RuntimeException($error);
        }
        /** @var ObjectDefinitionInterface $objectDefinition */
        $objectDefinition = $endpoint->getType($matches[1]);
        $objectDefinition->addField($field);

        $argAnnotations = $this->reader->getClassAnnotations($refClass);
        foreach ($argAnnotations as $argAnnotation) {
            if ($argAnnotation instanceof Annotation\Argument) {
                $this->resolveArgument($field, $argAnnotation);
            }
        }

        $field->setType(TypeUtil::normalize($annotation->type));
        $field->setList(TypeUtil::isTypeList($annotation->type));
        $field->setResolver($annotation->resolver ?? $refClass->getName());
        $field->setDeprecationReason($annotation->deprecationReason);
        $field->setDescription($annotation->description);
        $field->setComplexity($annotation->complexity);
        $field->setMaxConcurrentUsage($annotation->maxConcurrentUsage);

        foreach ($annotation->options as $option => $value) {
            $field->setMeta($option, $value);
        }

        if ($objectDefinition instanceof InterfaceDefinition) {
            $implementors = $objectDefinition->getImplementors();
            foreach ($implementors as $implementor) {
                $childType = $endpoint->getType($implementor);
                if ($childType instanceof FieldsAwareDefinitionInterface) {
                    $childType->addField($field);
                }
            }
        }
    }
367356
public function main()
    {
        if ($this->function === null && $this->expression === null) {
            throw new BuildException(
                "You must specify a function to execute or PHP expression to evalute.",
                $this->getLocation()
            );
        }

        if ($this->function !== null && $this->expression !== null) {
            throw new BuildException("You can specify function or expression, but not both.", $this->getLocation());
        }

        if ($this->expression !== null && !empty($this->params)) {
            throw new BuildException(
                "You cannot use nested <param> tags when evaluationg a PHP expression.",
                $this->getLocation()
            );
        }

        if ($this->function !== null) {
            $this->callFunction();
        } elseif ($this->expression !== null) {
            $this->evalExpression();
        }
    }
456284
private function setFieldValue($entity, \ReflectionProperty $reflectionProperty, $value)
    {
        if ($reflectionProperty) {
            $reflectionProperty->setAccessible(true);
            $value = $reflectionProperty->setValue($entity, $value);
        }
    }
224520
private function generateProxyMethod(\ReflectionMethod $method): string
    {
        if ($method->isConstructor()) {
            throw new \RuntimeException(sprintf(
                'Can not generate proxy method for constructor in class "%s".',
                $method->getDeclaringClass()->getName()
            ));
        }

        if ($method->isStatic()) {
            throw new \RuntimeException(sprintf(
                'Can not generate proxy method for static method "%s" in class "%s".',
                $method->getName(),
                $method->getDeclaringClass()->getName()
            ));
        }

        if ($method->isPrivate()) {
            throw new \RuntimeException(sprintf(
                'Can not generate proxy for private method "%s" in class "%s".',
                $method->getName(),
                $method->getDeclaringClass()->getName()
            ));
        }

        $proxyMethodParameters = [];
        $methodParameters = [];

        foreach ($method->getParameters() as $methodParameter) {
            $methodParameters[] = '$'.$methodParameter->getName();

            if ($methodParameter->getClass()) {
                $proxyMethodParameter = sprintf(
                    '\\%s %s',
                    $methodParameter->getClass()->getName(),
                    '$'.$methodParameter->getName()
                );
            } else if ($methodParameter->getType()) {
                $proxyMethodParameter = \sprintf(
                    '%s%s $%s',
                    $methodParameter->getType()->allowsNull() ? '?' : '',
                    $methodParameter->getType()->getName(),
                    $methodParameter->getName()
                );
            } else {
                $proxyMethodParameter = '$'.$methodParameter->getName();
            }

            if ($methodParameter->isOptional()) {
                $proxyMethodParameter .= ' = '.\var_export($methodParameter->getDefaultValue(), true);
            }

            $proxyMethodParameters[] = $proxyMethodParameter;
        }

        if ($method->isPublic()) {
            $availability = 'public';
        } else if ($method->isProtected()) {
            $availability = 'protected';
        } else {
            throw new \RuntimeException(sprintf(
                'Not support availability for method "%s" in class "%s".',
                $method->getName(),
                $method->getDeclaringClass()->getName()
            ));
        }

        $docComment = "/**\n * {@inheritdoc}\n */";
        $returnTypeHint = '';
        $returnResult = "\n\n    return \$result;";

        if ($method->getReturnType()) {
            $returnTypeHint = sprintf(
                ': %s%s%s',
                \class_exists($method->getReturnType()->getName()) ? '\\' : '',
                $method->getReturnType()->allowsNull() ? '?' : '',
                $method->getReturnType()->getName()
            );
        }

        if ($method->getReturnType() && 'void' === $method->getReturnType()->getName()) {
            $returnResult = '';
        }

        $templateVariables = [
            'docComment'            => $docComment,
            'availability'          => $availability,
            'name'                  => $method->getName(),
            'proxyMethodParameters' => \implode(', ', $proxyMethodParameters),
            'parameters'            => \implode(', ', $methodParameters),
            'beginArguments'        => null,
            'rollbackArguments'     => null,
            'commitArguments'       => null,
            'return_type_hint'      => $returnTypeHint,
            'return_result'         => $returnResult,
        ];

        $methodTemplate = $this->getTemplateForProxyMethod();
        $methodCode = $this->replaceVariables($methodTemplate, $templateVariables);
        $methodCode = $this->appendTabulationCharacter($methodCode, 1);

        return $methodCode;
    }
494236
protected function resolveArguments(
        ContainerInterface $container,
        \ReflectionMethod $method,
        array $parameters
    ) {
        try {
            //Getting set of arguments should be sent to requested method
            return $container->get(ResolverInterface::class)->resolveArguments(
                $method,
                $parameters
            );
        } catch (ArgumentException $e) {
            throw new ControllerException(
                "Missing/invalid parameter '{$e->getParameter()->name}'",
                ControllerException::BAD_ARGUMENT
            );
        } catch (ContainerExceptionInterface $e) {
            throw new ControllerException($e->getMessage(), ControllerException::ERROR, $e);
        }
    }
637958
public static function fromReflection(ReflectionFunction $reflectionFunction)
    {
        $name = self::extractShortNameFromFullyQualifiedName($reflectionFunction->getName());
        $namespace = self::extractNamespaceFromQualifiedName($reflectionFunction->getName());

        $function = new static($name, trim($reflectionFunction->getBody()));
        $function->setNamespace($namespace);
        foreach ($reflectionFunction->getParameters() as $parameter) {
            $function->addParameter(ParameterGenerator::fromReflection($parameter));
        }

        if ($reflectionFunction->getReflectionDocComment()->isEmpty() !== true) {
            $function->setDocumentation(
                DocCommentGenerator::fromReflection($reflectionFunction->getReflectionDocComment())
            );
        }

        return $function;
    }
209012
public static function fromReflection(ReflectionDocComment $reflectionDocComment)
    {
        $annotations = array();
        foreach ($reflectionDocComment->getAnnotationsCollection()->getAnnotations() as $reflectionTag) {
            $annotations[] = BaseTag::fromReflection($reflectionTag);
        }

        return new static($reflectionDocComment->getShortDescription(), $reflectionDocComment->getLongDescription(), $annotations);
    }
600474
public function generateProxyCode(\ReflectionClass $ref)
	{
		$methods = $this->collectProxyMethods($ref);
		$implements = ['\KoolKode\Context\Scope\ScopedProxyInterface'];
				
		$code = 'namespace ' . $ref->getNamespaceName() . ' { ';
		$code .= 'if(!class_exists(' . var_export($ref->name . '__scoped', true) . ', false)) { ';
		$code .= 'final class ' . $ref->getShortName() . '__scoped';
		
		if($ref->isInterface())
		{
			$implements[] = '\\' . $ref->name;
		}
		else
		{
			$code .= ' extends \\' . $ref->name;
		}
		
		$code .= ' implements ' . implode(', ', $implements) . ' { ';
		$code .= 'use \KoolKode\Context\Scope\ScopedProxyTrait; ';
		
		$code .= 'private $__K2Binding, $__K2Scope, $__K2Target; ';
		
		$code .= 'public final function __construct(\KoolKode\Context\Bind\BindingInterface $binding, \KoolKode\Context\Scope\ScopeManagerInterface $scope, \SplObjectStorage & $target) { ';
		$code .= '$this->__K2Binding = $binding; $this->__K2Scope = $scope; $this->__K2Target = & $target; ';
		
		$fieldNames = array_unique($this->collectRemovedFieldNames($ref));
		
		if(!empty($fieldNames))
		{
			$code .= ' unset(';
			
			foreach($fieldNames as $i => $name)
			{
				if($i != 0)
				{
					$code .= ', ';
				}
				
				$code .= '$this->' . $name;
			}
			
			$code .= ');';
		}
		
		$code.= ' } ';
		
		foreach($methods as $method)
		{
			$code .= $this->buildMethodSignature($method, true);
			
			$code .= ' { ';
			$code .= 'if(!$this->__K2Target->offsetExists($this)) { $this->__K2Scope->activateInstance($this); } ';
			$code .= 'return call_user_func_array([$this->__K2Target[$this], __FUNCTION__], func_get_args()); ';
			$code .= '} ';
		}
		
		return $code . ' } } } ';
	}