@param HttpServerDoc $doc

@return array

@throws \ReflectionException
962859
public function normalize(HttpServerDoc $doc)
    {
        return [
                'openapi' => '3.0.0',
            ]
            + $this->infoArray($doc)
            + $this->serverArray($doc)
            + $this->tagsArray($doc)
            + $this->pathsArray($doc)
            + $this->externalSchemaListArray($doc);
    }
707989
protected function pathsArray(HttpServerDoc $doc) : array
    {
        $paths = [];
        foreach ($doc->getMethodList() as $method) {
            $operationDoc = $this->operationDocNormalizer->normalize($method);

            // As JSON-RPC use only one endpoint
            // and openApi does not handle multiple request definition for the same endpoint
            // => create a fake (but usable) endpoint by using method id and '/../'
            $openApiHttpEndpoint = sprintf(
                '/%s/..%s',
                str_replace('/', '-', $method->getIdentifier()),
                $doc->getEndpoint() ?? ''
            );

            $paths[$openApiHttpEndpoint] = ['post' => $operationDoc];
        }

        return $this->appendIfValueHaveSiblings('paths', $paths);
    }
1074798
protected function getDocumentData($document)
    {
        if (is_array($document)) {
            $data = $document;
        } elseif ($document instanceof AbstractDocument) {
            $reflectionClass = new \ReflectionClass($document);
            $documentProperty = $reflectionClass->getParentClass()->getProperty('document');
            $documentProperty->setAccessible(true);
            $data = $documentProperty->getValue($document);
            foreach ($data as $key => &$value) {
                if ($value instanceof DocumentSerializableInterface) {
                    $value = $value->documentSerialize()->jsonSerialize();
                }
            }
        } else {
            throw new \Exception('Invalid data type, array or AbstractDocument expected');
        }

        return $data;
    }
1210253
public function getObjectPropertyAnnotations($document)
    {
        $cacheKey = "object_property_annotations_" . get_class($document);
        if (!$this->cache->contains($cacheKey)) {
            $refObject   = new \ReflectionObject($document);
            $annotations = array();
            foreach ($refObject->getProperties() as $property) {
                $annotation = $this->getPropertyAnnotation($property);
                if ($annotation) {
                    $annotations[$property->getName()] = $annotation;
                }
            }
            $this->cache->save($cacheKey, $annotations);
        }
        return $this->cache->fetch($cacheKey);
    }
261707
private function appendErrorsSchema(MethodDoc $docObject) : array
    {
        $docArray = [];
        // Create custom result schema only if provided
        if (count($docObject->getCustomErrorList()) || count($docObject->getGlobalErrorRefList())) {
            $docArray['errors'] = array_merge(
                array_map(
                    [$this->errorDocNormalizer, 'normalize'],
                    $docObject->getCustomErrorList()
                ),
                array_map(
                    function ($errorIdentifier) {
                        return ['$ref' => sprintf('#/errors/%s', $errorIdentifier)];
                    },
                    $docObject->getGlobalErrorRefList()
                )
            );
        }

        return $docArray;
    }
1131141
public function getMethods($type)
    {
        $result = [];
        if ($type !== false) {
            $typeNorm = $this->toolsType->normalizeType($type);
            /** @var \Zend\Code\Reflection\ClassReflection $reflection */
            $reflection = new \Zend\Code\Reflection\ClassReflection($typeNorm);
            /** @var \Zend\Code\Reflection\DocBlockReflection $docBlock */
            $docBlock = $reflection->getDocBlock();
            $annotatedMethods = $this->_processClassDocBlock($docBlock);
            /* process normal methods (not annotated) */
            $publicMethods = $reflection->getMethods(\ReflectionMethod::IS_PUBLIC);
            $generalMethods = $this->_processClassMethods($publicMethods);
            $merged = array_merge($generalMethods, $annotatedMethods);
            /* convert results to array form according Magento requirements to be saved in the cache */
            /** @var \Praxigento\Core\App\Reflection\Data\Method $item */
            foreach ($merged as $item) {
                $methodName = $item->getName();
                $entry = [
                    'type' => $item->getType(),
                    'isRequired' => $item->getIsRequired(),
                    'description' => $item->getDescription(),
                    'parameterCount' => $item->getParameterCount()
                ];
                $result[$methodName] = $entry;
            }
        }
        return $result;
    }
1275977
protected function extractParamAnnotations(string $docComment): array
    {
        $pattern = '/@param(?:\s+([^$"]\S+))?(?:\s+\$(\w+))?(?:\s+"([^"]++)")?/';

        if (!(bool)preg_match_all($pattern, $docComment, $matches, PREG_SET_ORDER)) {
            return [];
        }

        $annotations = [];

        foreach ($matches as $index => $match) {
            $annotations[$index] = isset($match[3]) && $match[3] !== '' ? $match[3] : null;
        }

        return $annotations;
    }
1308978
private function getRequirements(string $docComment): array
    {
        return array_map(
            function($tag) {
                preg_match('#@require ([^ ]*)#', $tag, $match);

                return $match[1];
            },
            array_filter(
                array_map(
                    'trim',
                    explode(
                        "\n",
                        str_replace(
                            "\r\n",
                            "\n",
                            $docComment
                        )
                    )
                ),
                function($docline) {
                    return 0 === strpos($docline, '* @require');
                }
            )
        );
    }
902794
public function getByEntity($entityClass, $id, $locale, $object = null)
    {
        $metadata = $this->structureMetadataFactory->getStructureMetadata('page', $object->getStructureType());

        return [
            '_controller' => $metadata->getController(),
            'view' => $metadata->getView(),
            'object' => $object,
            'structure' => $this->documentToStructure($object),
        ];
    }
442873
public function serializeDocument(DocumentInterface $document, bool $identifiersOnly = false): array
    {
        $result = [];

        if ($this->shouldContainData($document)) {
            $result['data'] = (!$document->shouldBeHandledAsCollection() && $document->data()->isEmpty()) ?
                null : $this->createData($document, $identifiersOnly);
        }

        if (!$document->metaInformation()->isEmpty()) {
            $result['meta'] = $document->metaInformation()->all();
        }

        if (!$document->links()->isEmpty()) {
            foreach ($document->links()->all() as $link) {
                $result['links'][$link->name()] = $this->serializeLink($link);
            }
        }

        if (!$document->included()->isEmpty()) {
            foreach ($document->included()->all() as $resource) {
                $result['included'][] = $this->serializeResource(
                    $resource,
                    false
                );
            }
        }

        if (!$document->errors()->isEmpty()) {
            foreach ($document->errors()->all() as $error) {
                $result['errors'][] = $this->serializeError($error);
            }
        }

        // informations about json api
        $result['jsonapi'] = [
            'version' => '1.0'
        ];

        return $result;
    }
496530
public function setDocument($doc)
    {
        $this->clearDocument();
        $doc = json_decode(json_encode($doc)); // ensure we are working with an object

        // set known properties
        if (!empty($doc->version)) {
            $this->version = $doc->version;
        }
        if (!empty($doc->href)) {
            $this->href = $doc->href;
        }
        if (!empty($doc->scope)) {
            $this->scope = $doc->scope;
        }
        if (!empty($doc->attributes)) {
            $this->attributes = $doc->attributes;
        }
        if (!empty($doc->links)) {
            $this->links = $doc->links;
        }
        if (!empty($doc->items)) {
            $this->items = $doc->items;
        }
        if (!empty($doc->errors)) {
            $this->errors = $doc->errors;
        }

        // get/set static links (preserving them between sets)
        foreach (self::$_staticLinkNames as $name) {
            if (empty($this->links->$name)) {
                $this->links->$name = self::$_staticLinks->$name;
            } else {
                self::$_staticLinks->$name = $this->links->$name;
            }
        }
        return $this;
    }
442477
protected function getMethodErrorsExternalSchemaList(ServerDoc $doc) : array
    {
        $list = [];
        foreach ($doc->getMethodList() as $method) {
            foreach ($method->getCustomErrorList() as $errorDoc) {
                $key = $this->definitionRefResolver->getErrorDefinitionId(
                    $errorDoc,
                    DefinitionRefResolver::CUSTOM_ERROR_DEFINITION_TYPE
                );
                $list[$key] = $this->errorDocNormalizer->normalize($errorDoc);
            }
        }

        return $list;
    }
890653
public function normalize(ServerDoc $doc) : array
    {
        // Info
        $rawInfo = $tagsDoc = $errorsDoc = [];
        if (null !== $doc->getName()) {
            $rawInfo['info']['name'] = $doc->getName();
        }
        if (null !== $doc->getVersion()) {
            $rawInfo['info']['version'] = $doc->getVersion();
        }

        // Tags
        $tagDocList = array_map([$this->tagDocNormalizer, 'normalize'], $doc->getTagList());
        if (count($tagDocList)) {
            $tagsDoc['tags'] = $tagDocList;
        }

        // Errors
        $serverErrorList = array_map([$this->errorDocNormalizer, 'normalize'], $doc->getServerErrorList());
        $globalErrorList = array_map([$this->errorDocNormalizer, 'normalize'], $doc->getGlobalErrorList());
        $errorList = array_merge($serverErrorList, $globalErrorList);
        if (count($errorList)) {
            $errorsDoc['errors'] = $errorList;
        }

        return $rawInfo
            + $tagsDoc
            + ['methods' => array_map([$this->methodDocNormalizer, 'normalize'], $doc->getMethodList())]
            + $errorsDoc;
    }
680973
protected function parseDocBlock(ReflectionMethod $method)
    {
        $comment = $method->getDocComment();
        $phpdoc = new DocBlock($comment);

        return [
            'short' => $phpdoc->getShortDescription(),
            'long' => $phpdoc->getLongDescription()->getContents(),
            'tags' => $phpdoc->getTags(),
        ];
    }
1108076
public function create($host = null) : HttpServerDoc
    {
        $serverDoc = new HttpServerDoc();
        if (null !== $this->jsonRpcEndpoint) {
            $serverDoc->setEndpoint($this->jsonRpcEndpoint);
        }
        if (null !== $host) {
            $serverDoc->setHost($host);
        }

        $this->appendMethodsDoc($serverDoc);

        $event = new ServerDocCreatedEvent($serverDoc);
        $this->dispatcher->dispatch($event::EVENT_NAME, $event);

        return $serverDoc;
    }
965981
private function processDocument(Document $document, $exposedPrefix = '')
    {
        $result = [];
        foreach ($document->getFields() as $field) {
            if ($field instanceof Field) {
                if ($field->getType() === 'extref') {
                    $result[] = $exposedPrefix.$field->getExposedName();
                }
            } elseif ($field instanceof ArrayField) {
                if ($field->getItemType() === 'extref') {
                    $result[] = $exposedPrefix.$field->getExposedName().'.0';
                }
            } elseif ($field instanceof EmbedOne) {
                $result = array_merge(
                    $result,
                    $this->processDocument(
                        $field->getDocument(),
                        $exposedPrefix.$field->getExposedName().'.'
                    )
                );
            } elseif ($field instanceof EmbedMany) {
                $result = array_merge(
                    $result,
                    $this->processDocument(
                        $field->getDocument(),
                        $exposedPrefix.$field->getExposedName().'.0.'
                    )
                );
            }
        }

        return $result;
    }
823413
private function getTypesFromVarComment(string $property, ReflectionClass $traitReflection): array
    {
        $docComment = $this->reflectionClass->getProperty($property)->getDocComment();
        \preg_match('%@var\s*?(.+)%', $docComment, $matches);
        $traitCode = \ts\file_get_contents($traitReflection->getFileName());
        $types     = \explode('|', $matches[1]);
        $return    = [];
        foreach ($types as $type) {
            $type = \trim($type);
            if ('null' === $type) {
                continue;
            }
            if ('ArrayCollection' === $type) {
                continue;
            }
            $arrayNotation = '';
            if ('[]' === substr($type, -2)) {
                $type          = substr($type, 0, -2);
                $arrayNotation = '[]';
            }
            $pattern = "%^use (.+?)\\\\${type}(;| |\[)%m";
            \preg_match($pattern, $traitCode, $matches);
            if (!isset($matches[1])) {
                throw new \RuntimeException(
                    'Failed finding match for type ' . $type . ' in ' . $traitReflection->getFileName()
                );
            }
            $return[] = $matches[1] . '\\' . $type . $arrayNotation;
        }

        return $return;
    }