Completed
Pull Request — master (#570)
by
unknown
01:17
created

Generator::fetchQueryParameters()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 4
rs 10
c 0
b 0
f 0
cc 1
nc 1
nop 5
1
<?php
2
3
namespace Mpociot\ApiDoc\Tools;
4
5
use ReflectionClass;
6
use ReflectionMethod;
7
use Illuminate\Routing\Route;
8
use Mpociot\ApiDoc\Tools\Traits\ParamHelpers;
9
10
class Generator
11
{
12
    use ParamHelpers;
13
14
    /**
15
     * @var DocumentationConfig
16
     */
17
    private $config;
18
19
    public function __construct(DocumentationConfig $config = null)
20
    {
21
        // If no config is injected, pull from global
22
        $this->config = $config ?: new DocumentationConfig(config('apidoc'));
23
    }
24
25
    /**
26
     * @param Route $route
27
     *
28
     * @return mixed
29
     */
30
    public function getUri(Route $route)
31
    {
32
        return $route->uri();
33
    }
34
35
    /**
36
     * @param Route $route
37
     *
38
     * @return mixed
39
     */
40
    public function getMethods(Route $route)
41
    {
42
        return array_diff($route->methods(), ['HEAD']);
43
    }
44
45
    /**
46
     * @param \Illuminate\Routing\Route $route
47
     * @param array $rulesToApply Rules to apply when generating documentation for this route
48
     *
49
     * @return array
50
     */
51
    public function processRoute(Route $route, array $rulesToApply = [])
52
    {
53
        list($controllerName, $methodName) = Utils::getRouteClassAndMethodNames($route->getAction());
54
        $controller = new ReflectionClass($controllerName);
55
        $method = $controller->getMethod($methodName);
56
57
        $parsedRoute = [
58
            'id' => md5($this->getUri($route).':'.implode($this->getMethods($route))),
59
            'methods' => $this->getMethods($route),
60
            'uri' => $this->getUri($route),
61
            'boundUri' => Utils::getFullUrl($route, $rulesToApply['bindings'] ?? ($rulesToApply['response_calls']['bindings'] ?? [])),
62
        ];
63
        $metadata = $this->fetchMetadata($controller, $method, $route, $rulesToApply, $parsedRoute);
64
        $parsedRoute['metadata'] = $metadata;
65
        $bodyParameters = $this->fetchBodyParameters($controller, $method, $route, $rulesToApply, $parsedRoute);
66
        $parsedRoute['bodyParameters'] = $bodyParameters;
67
        $parsedRoute['cleanBodyParameters'] = $this->cleanParams($bodyParameters);
68
69
        $queryParameters = $this->fetchQueryParameters($controller, $method, $route, $rulesToApply, $parsedRoute);
70
        $parsedRoute['queryParameters'] = $queryParameters;
71
        $parsedRoute['cleanQueryParameters'] = $this->cleanParams($queryParameters);
72
73
        $responses = $this->fetchResponses($controller, $method, $route, $rulesToApply, $parsedRoute);
74
        $parsedRoute['response'] = $responses;
75
        $parsedRoute['showresponse'] = ! empty($responses);
76
77
        $parsedRoute['headers'] = $rulesToApply['headers'] ?? [];
78
79
        // Currently too lazy to tinker with Blade files; change this later
80
        unset($parsedRoute['metadata']);
81
        $parsedRoute += $metadata;
82
83
        return $parsedRoute;
84
    }
85
86
    protected function fetchMetadata(ReflectionClass $controller, ReflectionMethod $method, Route $route, array $rulesToApply, array $context = [])
87
    {
88
        $context['metadata'] = [
89
            'groupName' => $this->config->get('default_group'),
90
            'groupDescription' => '',
91
            'title' => '',
92
            'description' => '',
93
            'authenticated' => false,
94
        ];
95
96
        return $this->iterateThroughStrategies('metadata', $context, [$route, $controller, $method, $rulesToApply]);
97
    }
98
99
    protected function fetchBodyParameters(ReflectionClass $controller, ReflectionMethod $method, Route $route, array $rulesToApply, array $context = [])
100
    {
101
        return $this->iterateThroughStrategies('bodyParameters', $context, [$route, $controller, $method, $rulesToApply]);
102
    }
103
104
    protected function fetchQueryParameters(ReflectionClass $controller, ReflectionMethod $method, Route $route, array $rulesToApply, array $context = [])
105
    {
106
        return $this->iterateThroughStrategies('queryParameters', $context, [$route, $controller, $method, $rulesToApply]);
107
    }
108
109
    protected function fetchResponses(ReflectionClass $controller, ReflectionMethod $method, Route $route, array $rulesToApply, array $context = [])
110
    {
111
        $responses = $this->iterateThroughStrategies('responses', $context, [$route, $controller, $method, $rulesToApply]);
112
        if (count($responses)) {
113
            return collect($responses)->map(function (string $response, int $status) {
114
                return [
115
                    'status' => $status ?: 200,
116
                    'content' => $response,
117
                ];
118
            })->values()->toArray();
119
        }
120
121
        return null;
122
    }
123
124
    protected function iterateThroughStrategies(string $key, array $context, array $arguments)
125
    {
126
        $strategies = $this->config->get("strategies.$key", []);
127
        $context[$key] = $context[$key] ?? [];
128
        foreach ($strategies as $strategyClass) {
129
            $strategy = new $strategyClass($this->config);
130
            $arguments[] = $context;
131
            $results = $strategy(...$arguments);
132
            if (! is_null($results)) {
133
                foreach ($results as $index => $item) {
134
                    // Using a for loop rather than array_merge or +=
135
                    // so it does not renumber numeric keys
136
                    // and also allows values to be overwritten
137
138
                    // Don't allow overwriting if an empty value is trying to replace a set one
139
                    if (! in_array($context[$key], [null, ''], true) && in_array($item, [null, ''], true)) {
140
                        continue;
141
                    } else {
142
                        $context[$key][$index] = $item;
143
                    }
144
                }
145
            }
146
        }
147
148
        return $context[$key];
149
    }
150
}
151