ApiDocExtractor::buildInput()   C
last analyzed

Complexity

Conditions 7
Paths 4

Size

Total Lines 23
Code Lines 16

Duplication

Lines 0
Ratio 0 %

Importance

Changes 5
Bugs 1 Features 0
Metric Value
c 5
b 1
f 0
dl 0
loc 23
rs 6.7272
cc 7
eloc 16
nc 4
nop 2
1
<?php
2
3
/*
4
 * This file is part of the Kreta package.
5
 *
6
 * (c) Beñat Espiña <[email protected]>
7
 * (c) Gorka Laucirica <[email protected]>
8
 *
9
 * For the full copyright and license information, please view the LICENSE
10
 * file that was distributed with this source code.
11
 */
12
13
namespace Kreta\SimpleApiDocBundle\Extractor;
14
15
use Doctrine\Common\Annotations\Reader;
16
use Kreta\SimpleApiDocBundle\Parser\ValidationParser;
17
use Nelmio\ApiDocBundle\Annotation\ApiDoc;
18
use Nelmio\ApiDocBundle\Extractor\ApiDocExtractor as BaseApiDocExtractor;
19
use Nelmio\ApiDocBundle\Util\DocCommentExtractor;
20
use Symfony\Bundle\FrameworkBundle\Controller\ControllerNameParser;
21
use Symfony\Component\DependencyInjection\ContainerInterface;
22
use Symfony\Component\Routing\Route;
23
use Symfony\Component\Routing\RouterInterface;
24
25
/**
26
 * Api Doc Extractor class.
27
 *
28
 * @author Beñat Espiña <[email protected]>
29
 */
30
class ApiDocExtractor extends BaseApiDocExtractor
31
{
32
    const ANNOTATION_CLASS = 'Kreta\\SimpleApiDocBundle\\Annotation';
33
34
    /**
35
     * The validation parser.
36
     *
37
     * @var \Kreta\SimpleApiDocBundle\Parser\ValidationParser
38
     */
39
    private $validationParser;
40
41
    /**
42
     * Constructor.
43
     *
44
     * @param ContainerInterface   $container            The container
45
     * @param RouterInterface      $router               The router
46
     * @param Reader               $reader               The reader
47
     * @param DocCommentExtractor  $commentExtractor     The comment extractor
48
     * @param ControllerNameParser $controllerNameParser Controller name parser
49
     * @param array                $handlers             Array that contains handlers
50
     * @param array                $annotationsProviders Annotation providers
51
     * @param ValidationParser     $validationParser     The validation parser
52
     */
53
    public function __construct(
54
        ContainerInterface $container,
55
        RouterInterface $router,
56
        Reader $reader,
57
        DocCommentExtractor $commentExtractor,
58
        ControllerNameParser $controllerNameParser,
59
        array $handlers,
60
        array $annotationsProviders,
61
        ValidationParser $validationParser
62
    ) {
63
        parent::__construct(
64
            $container,
65
            $router,
66
            $reader,
67
            $commentExtractor,
68
            $controllerNameParser,
69
            $handlers,
70
            $annotationsProviders
71
        );
72
        $this->validationParser = $validationParser;
73
    }
74
75
    /**
76
     * {@inheritdoc}
77
     */
78
    protected function extractData(ApiDoc $annotation, Route $route, \ReflectionMethod $method)
79
    {
80
        $annotation->setRoute($route);
81
        $annotation = $this->buildInput($annotation);
82
        $annotation = $this->buildOutput($annotation);
83
        $annotation = parent::extractData($annotation, $route, $method);
84
        $statusCodes = $annotation->toArray()['statusCodes'];
85
        if (!(array_key_exists(400, $statusCodes)) || $statusCodes[400][0] === null) {
86
            $validations = $this->validationParser->getValidations(
87
                str_replace(['Interfaces\\', 'Interface'], '', $annotation->getOutput())
88
            );
89
            if (count($validations) > 0) {
90
                $annotation->addStatusCode(400, $validations);
91
            }
92
        }
93
94
        return $annotation;
95
    }
96
97
    /**
98
     * Method that adds the input property of ApiDoc
99
     * getting the form type's fully qualified name.
100
     *
101
     * @param ApiDoc     $annotation The annotation
102
     * @param array|null $data       The data given
103
     *
104
     * @return ApiDoc
105
     */
106
    public function buildInput(ApiDoc $annotation, $data = null)
107
    {
108
        $annotationReflection = new \ReflectionClass('Nelmio\ApiDocBundle\Annotation\ApiDoc');
109
        $inputReflection = $annotationReflection->getProperty('input');
110
        $inputReflection->setAccessible(true);
111
112
        if (!(isset($data['input']) || $data['input'] === null) || empty($data['input'])) {
113
            if ($annotation->toArray()['method'] === 'POST' || $annotation->toArray()['method'] === 'PUT') {
114
                $actionName = $annotation->getRoute()->getDefault('_controller');
115
                $controllerClass = substr($actionName, 0, strpos($actionName, '::'));
116
                $reflectionClass = new \ReflectionClass(substr($controllerClass, strpos($controllerClass, ':')));
117
                $class = str_replace('Controller', '', $reflectionClass->getShortName());
118
                $inputType = 'Kreta\\Component\\' . $class . '\\Form\\Type\\' . $class . 'Type';
119
                if (class_exists($inputType)) {
120
                    $inputReflection->setValue($annotation, $inputType);
121
                }
122
            }
123
        } else {
124
            $inputReflection->setValue($annotation, $data['input']);
125
        }
126
127
        return $annotation;
128
    }
129
130
    /**
131
     * Method that adds the output property of ApiDoc
132
     * getting the model's fully qualified name.
133
     *
134
     * @param ApiDoc     $annotation The annotation
135
     * @param array|null $data       The data given
136
     *
137
     * @return ApiDoc
138
     */
139
    public function buildOutput(ApiDoc $annotation, $data = null)
140
    {
141
        $annotationReflection = new \ReflectionClass('Nelmio\ApiDocBundle\Annotation\ApiDoc');
142
        $outputReflection = $annotationReflection->getProperty('output');
143
        $outputReflection->setAccessible(true);
144
        if (!(isset($data['output']) || $data['output'] === null) || empty($data['output'])) {
145
            if ($annotation->toArray()['method'] === 'POST' || $annotation->toArray()['method'] === 'PUT') {
146
                $actionName = $annotation->getRoute()->getDefault('_controller');
147
                $reflectionMethod = new \ReflectionMethod($actionName);
148
                $phpdoc = $reflectionMethod->getDocComment();
149
                $return = substr($phpdoc, strpos($phpdoc, '@return'));
150
                $returnType = str_replace(['@return \\', '*', '[]', 'array<\\', '>'], '', $return);
151
                $returnType = substr($returnType, 0, strpos($returnType, strstr($returnType, "\n")));
152
                $returnType = preg_replace("/\r\n|\r|\n|\\/\\s+/", '', $returnType);
153
154
                if (class_exists($returnType) || interface_exists($returnType)) {
155
                    $outputReflection->setValue($annotation, $returnType);
156
                }
157
            }
158
        } else {
159
            $outputReflection->setValue($annotation, $data['output']);
160
        }
161
162
        return $annotation;
163
    }
164
}
165