ApiDocExtractor::__construct()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 21
Code Lines 18

Duplication

Lines 0
Ratio 0 %

Importance

Changes 4
Bugs 0 Features 0
Metric Value
c 4
b 0
f 0
dl 0
loc 21
rs 9.3142
cc 1
eloc 18
nc 1
nop 8

How to fix   Many Parameters   

Many Parameters

Methods with many parameters are not only hard to understand, but their parameters also often become inconsistent when you need more, or different data.

There are several approaches to avoid long parameter lists:

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