Completed
Push — master ( de84eb...d1f862 )
by Jaap
18s queued 11s
created

Router   A

Complexity

Total Complexity 19

Size/Duplication

Total Lines 214
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 11

Test Coverage

Coverage 0%

Importance

Changes 0
Metric Value
dl 0
loc 214
ccs 0
cts 118
cp 0
rs 10
c 0
b 0
f 0
wmc 19
lcom 1
cbo 11

5 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 13 1
B configure() 0 133 7
A generate() 0 9 3
A match() 0 11 3
A generateUrlForDescriptor() 0 24 5
1
<?php
2
3
declare(strict_types=1);
4
5
/**
6
 * This file is part of phpDocumentor.
7
 *
8
 * For the full copyright and license information, please view the LICENSE
9
 * file that was distributed with this source code.
10
 *
11
 * @link http://phpdoc.org
12
 */
13
14
namespace phpDocumentor\Transformer\Router;
15
16
use ArrayObject;
17
use InvalidArgumentException;
18
use phpDocumentor\Descriptor\ClassDescriptor;
19
use phpDocumentor\Descriptor\ConstantDescriptor;
20
use phpDocumentor\Descriptor\DescriptorAbstract;
21
use phpDocumentor\Descriptor\FileDescriptor;
22
use phpDocumentor\Descriptor\FunctionDescriptor;
23
use phpDocumentor\Descriptor\InterfaceDescriptor;
24
use phpDocumentor\Descriptor\MethodDescriptor;
25
use phpDocumentor\Descriptor\NamespaceDescriptor;
26
use phpDocumentor\Descriptor\PackageDescriptor;
27
use phpDocumentor\Descriptor\PropertyDescriptor;
28
use phpDocumentor\Descriptor\TraitDescriptor;
29
use phpDocumentor\Reflection\DocBlock\Tags\Reference\Fqsen;
30
use phpDocumentor\Reflection\DocBlock\Tags\Reference\Url;
31
use phpDocumentor\Transformer\Router\UrlGenerator\QualifiedNameToUrlConverter;
32
use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
33
34
/**
35
 * The default for phpDocumentor.
36
 */
37
class Router extends ArrayObject
38
{
39
    /** @var UrlGenerator\FqsenDescriptor */
40
    private $fqsenUrlGenerator;
41
42
    /** @var QualifiedNameToUrlConverter */
43
    private $converter;
44
45
    /** @var UrlGeneratorInterface */
46
    private $urlGenerator;
47
48
    public function __construct(
49
        UrlGenerator\FqsenDescriptor $fqsenUrlGenerator,
50
        QualifiedNameToUrlConverter $converter,
51
        UrlGeneratorInterface $urlGenerator
52
    ) {
53
        $this->fqsenUrlGenerator = $fqsenUrlGenerator;
54
        $this->converter = $converter;
55
        $this->urlGenerator = $urlGenerator;
56
57
        parent::__construct();
58
59
        $this->configure();
60
    }
61
62
    /**
63
     * Configuration function to add routing rules to a router.
64
     */
65
    public function configure() : void
66
    {
67
        // @codingStandardsIgnoreStart
68
        $this[] = new Rule(
69
            function ($node) {
70
                return $node instanceof FileDescriptor;
71
            },
72
            function (FileDescriptor $node) : string {
73
                return $this->generateUrlForDescriptor('file', $node->getPath());
74
            }
75
        );
76
        $this[] = new Rule(
77
            function ($node) {
78
                return $node instanceof PackageDescriptor;
79
            },
80
            function (PackageDescriptor $node) : string {
81
                return $this->generateUrlForDescriptor(
82
                    'package',
83
                    (string) $node->getFullyQualifiedStructuralElementName()
84
                );
85
            }
86
        );
87
        $this[] = new Rule(
88
            function ($node) {
89
                return $node instanceof NamespaceDescriptor;
90
            },
91
            function (NamespaceDescriptor $node) : string {
92
                return $this->generateUrlForDescriptor(
93
                    'namespace',
94
                    (string) $node->getFullyQualifiedStructuralElementName()
95
                );
96
            }
97
        );
98
        $this[] = new Rule(
99
            function ($node) : bool {
100
                return $node instanceof ClassDescriptor || $node instanceof InterfaceDescriptor || $node instanceof TraitDescriptor;
101
            },
102
            function (DescriptorAbstract $node) : string {
103
                return $this->generateUrlForDescriptor(
104
                    'class',
105
                    (string) $node->getFullyQualifiedStructuralElementName()
106
                );
107
            }
108
        );
109
        $this[] = new Rule(
110
            function ($node) {
111
                return $node instanceof ConstantDescriptor
112
                    && ($node->getParent() instanceof FileDescriptor || !$node->getParent());
113
            },
114
            function (ConstantDescriptor $node) : string {
115
                return $this->generateUrlForDescriptor(
116
                    'namespace',
117
                    (string) $node->getNamespace(),
118
                    'constant_' . $node->getName()
119
                );
120
            }
121
        );
122
        $this[] = new Rule(
123
            function ($node) {
124
                return $node instanceof ConstantDescriptor
125
                    && !($node->getParent() instanceof FileDescriptor || !$node->getParent());
126
            },
127
            function (ConstantDescriptor $node) : string {
128
                return $this->generateUrlForDescriptor(
129
                    'class',
130
                    (string) $node->getParent()->getFullyQualifiedStructuralElementName(),
131
                    'constant_' . $node->getName()
132
                );
133
            }
134
        );
135
        $this[] = new Rule(
136
            function ($node) {
137
                return $node instanceof MethodDescriptor;
138
            },
139
            function (MethodDescriptor $node) : string {
140
                return $this->generateUrlForDescriptor(
141
                    'class',
142
                    (string) $node->getParent()->getFullyQualifiedStructuralElementName(),
143
                    'method_' . $node->getName()
144
                );
145
            }
146
        );
147
        $this[] = new Rule(
148
            function ($node) {
149
                return $node instanceof FunctionDescriptor;
150
            },
151
            function (FunctionDescriptor $node) : string {
152
                return $this->generateUrlForDescriptor(
153
                    'namespace',
154
                    (string) $node->getNamespace(),
155
                    'function_' . $node->getName()
156
                );
157
            }
158
        );
159
        $this[] = new Rule(
160
            function ($node) {
161
                return $node instanceof PropertyDescriptor;
162
            },
163
            function (PropertyDescriptor $node) : string {
164
                return $this->generateUrlForDescriptor(
165
                    'class',
166
                    (string) $node->getParent()->getFullyQualifiedStructuralElementName(),
167
                    'property_' . $node->getName()
168
                );
169
            }
170
        );
171
        $this[] = new Rule(
172
            function ($node) {
173
                return $node instanceof Fqsen;
174
            }, $this->fqsenUrlGenerator
175
        );
176
177
        // if this is a link to an external page; return that URL
178
        $this[] = new Rule(
179
            function ($node) {
180
                return $node instanceof Url;
181
            },
182
            function ($node) {
183
                return (string) $node;
184
            }
185
        );
186
187
        // do not generate a file for every unknown type
188
        $this[] = new Rule(
189
            function () {
190
                return true;
191
            },
192
            function () {
193
                return false;
194
            }
195
        );
196
        // @codingStandardsIgnoreEnd
197
    }
198
199
    public function generate($node) : ?string
200
    {
201
        $rule = $this->match($node);
202
        if (!$rule) {
203
            return null;
204
        }
205
206
        return $rule->generate($node) ?: null;
207
    }
208
209
    /**
210
     * Tries to match the provided node with one of the rules in this router.
211
     *
212
     * @param string|DescriptorAbstract $node
213
     */
214
    private function match($node) : ?Rule
215
    {
216
        /** @var Rule $rule */
217
        foreach ($this as $rule) {
218
            if ($rule->match($node)) {
219
                return $rule;
220
            }
221
        }
222
223
        return null;
224
    }
225
226
    private function generateUrlForDescriptor(string $type, string $fqsen, string $fragment = '') : string
227
    {
228
        switch ($type) {
229
            case 'namespace':
230
                $name = $this->converter->fromNamespace($fqsen);
231
                break;
232
            case 'class':
233
                $name = $this->converter->fromClass($fqsen);
234
                break;
235
            case 'package':
236
                $name = $this->converter->fromPackage($fqsen);
237
                break;
238
            case 'file':
239
                $name = $this->converter->fromFile($fqsen);
240
                break;
241
            default:
242
                throw new InvalidArgumentException('Unknown url type');
243
        }
244
245
        return $this->urlGenerator->generate(
246
            $type,
247
            ['name' => $name, '_fragment' => $fragment]
248
        );
249
    }
250
}
251