Completed
Push — master ( f7cff5...a21d42 )
by Yaro
01:21
created

ApiDocs   A

Complexity

Total Complexity 20

Size/Duplication

Total Lines 136
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 0

Importance

Changes 2
Bugs 0 Features 0
Metric Value
wmc 20
c 2
b 0
f 0
lcom 1
cbo 0
dl 0
loc 136
rs 10

3 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 4 1
A show() 0 6 1
D getEndpoints() 0 117 18
1
<?php 
2
3
namespace Yaro\ApiDocs;
4
5
use ReflectionClass;
6
use Illuminate\Routing\Router;
7
8
class ApiDocs
9
{
10
    
11
    private $router;
12
    
13
    public function __construct(Router $router)
14
    {
15
        $this->router = $router;
16
    } // end __construct
17
18
    public function show()
19
    {
20
        $endpoints = $this->getEndpoints();
21
        
22
        return view('apidocs::docs', compact('endpoints'));
23
    } // end show
24
    
25
    private function getEndpoints()
26
    {
27
        $disabledNamespaces = config('yaro.apidocs.disabled_namespaces', []);
28
        $prefix = config('yaro.apidocs.prefix', 'api');
29
        
30
        $endpoints = [];
31
        
32
        $splitCamelCaseRegexp = '/(?#! splitCamelCase Rev:20140412)
33
            # Split camelCase "words". Two global alternatives. Either g1of2:
34
              (?<=[a-z])      # Position is after a lowercase,
35
              (?=[A-Z])       # and before an uppercase letter.
36
            | (?<=[A-Z])      # Or g2of2; Position is after uppercase,
37
              (?=[A-Z][a-z])  # and before upper-then-lower case.
38
            /x';
39
        
40
        foreach ($this->router->getRoutes() as $route) {
41
            if (!preg_match('~^'. preg_quote($prefix) .'~', $route->uri)) {
42
                continue;
43
            }
44
            
45
            $action = $route->action['uses'];
46
            if (is_object($action)) {
47
                continue;
48
            }
49
            
50
            $array = explode("@", $route->action['controller']);
51
            $class = $array[0];
52
            $method = $array[1];
53
            
54
            if (!class_exists($class) || !method_exists($class, $method)) {
55
                continue;
56
            }
57
            
58
            $reflector = new ReflectionClass($class);
59
            
60
            $docs = explode("\n", $reflector->getMethod($method)->getDocComment());
61
            $docs = array_filter($docs);
62
            if (!$docs) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $docs of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
63
                continue;
64
            }
65
            
66
            foreach ($docs as &$line) {
67
                $line = preg_replace('~\s*\*\s*~', '', $line);
68
                $line = preg_replace('~/~', '', $line);
69
            }
70
            $docs = array_values(array_filter($docs));
71
            
72
            $title = array_shift($docs);
73
            $description = '';
74
            $params = [];
75
            $checkForLongDescription = true;
76
            foreach ($docs as $line) {
77
                if ($checkForLongDescription && !preg_match('~^@\w+~', $line)) {
78
                    $description .= trim($line) .' ';
79
                } elseif (preg_match('~^@\w+~', $line)) {
80
                    $checkForLongDescription = false;
81
                    if (preg_match('~^@param~', $line)) {
82
                        $paramChunks = explode(' ', $line);
83
                        $paramChunks = array_filter($paramChunks, function($val) {
84
                            return $val !== '';
85
                        });
86
                        unset($paramChunks[0]);
87
                        
88
                        $paramType = array_shift($paramChunks);
89
                        $paramName = substr(array_shift($paramChunks), 1);
90
                        $params[$paramName] = [
91
                            'type'        => $paramType,
92
                            'name'        => $paramName,
93
                            'description' => implode(' ', $paramChunks),
94
                        ];
95
                    }
96
                }
97
            }
98
            
99
            
100
            $chunks = explode('\\', $class);
101
            foreach ($chunks as $index => $chunk) {
102
                if (in_array($chunk, $disabledNamespaces)) {
103
                    unset($chunks[$index]);
104
                    continue;
105
                }
106
                
107
                $chunk = preg_replace('~Controller$~', '', $chunk);
108
                if ($chunk) {
109
                    $chunk = preg_split($splitCamelCaseRegexp, $chunk);
110
                    $chunks[$index] = implode(' ', $chunk);
111
                }
112
                
113
            }
114
               
115
            $key = implode('.', $chunks);
116
            
117
            preg_match_all('~{(\w+)}~', $route->uri, $matches);
118
            $uriParams = isset($matches[1]) ? $matches[1] : [];
119
            
120
            $endpoints[$key][] = [
121
                'hash'    => strtolower(preg_replace('~\s+~', '-', $key) .'::'. $route->methods[0] .'::'. implode('-', preg_split($splitCamelCaseRegexp, $method))),
122
                'uri'     => $route->uri,
123
                'name'    => $method,
124
                'methods' => $route->methods,
125
                'docs' => [
126
                    'title'       => $title, 
127
                    'description' => trim($description), 
128
                    'params'      => $params,
129
                    'uri_params'  => $uriParams,
130
                ],
131
            ];
132
        }
133
        
134
        ksort($endpoints);
135
    
136
        $sorted = array();
137
        foreach($endpoints as $key => $val) {
138
            ins($sorted, explode('.', $key), $val);
139
        }
140
        return $sorted;
141
    } // end getEndpoints
142
    
143
}
144