This project does not seem to handle request data directly as such no vulnerable execution paths were found.
include
, or for example
via PHP's auto-loading mechanism.
These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more
1 | <?php |
||
2 | declare(strict_types=1); |
||
3 | |||
4 | /** |
||
5 | * This file is part of phpDocumentor. |
||
6 | * |
||
7 | * For the full copyright and license information, please view the LICENSE |
||
8 | * file that was distributed with this source code. |
||
9 | * |
||
10 | * @author Mike van Riel <[email protected]> |
||
11 | * @copyright 2010-2018 Mike van Riel / Naenius (http://www.naenius.com) |
||
12 | * @license http://www.opensource.org/licenses/mit-license.php MIT |
||
13 | * @link http://phpdoc.org |
||
14 | */ |
||
15 | |||
16 | namespace phpDocumentor\Compiler\Pass; |
||
17 | |||
18 | use phpDocumentor\Compiler\CompilerPassInterface; |
||
19 | use phpDocumentor\Descriptor\Collection; |
||
20 | use phpDocumentor\Descriptor\DescriptorAbstract; |
||
21 | use phpDocumentor\Descriptor\ProjectDescriptor; |
||
22 | use phpDocumentor\Reflection\DocBlock\DescriptionFactory; |
||
23 | use phpDocumentor\Reflection\DocBlock\StandardTagFactory; |
||
24 | use phpDocumentor\Reflection\DocBlock\Tag; |
||
25 | use phpDocumentor\Reflection\DocBlock\Tags\Link; |
||
26 | use phpDocumentor\Reflection\DocBlock\Tags\Reference\Fqsen; |
||
27 | use phpDocumentor\Reflection\DocBlock\Tags\See; |
||
28 | use phpDocumentor\Reflection\FqsenResolver; |
||
29 | use phpDocumentor\Reflection\TypeResolver; |
||
30 | use phpDocumentor\Reflection\Types\Context; |
||
31 | use phpDocumentor\Transformer\Router\Queue; |
||
32 | |||
33 | /** |
||
34 | * This step in the compilation process iterates through all elements and scans their descriptions for an inline `@see` |
||
35 | * or `@link` tag and resolves them to a markdown link. |
||
36 | */ |
||
37 | class ResolveInlineLinkAndSeeTags implements CompilerPassInterface |
||
38 | { |
||
39 | const COMPILER_PRIORITY = 9002; |
||
40 | |||
41 | const REGEX_INLINE_LINK_OR_SEE_TAG = '/\{\@(see|link)[\ ]+([^\}]+)\}/'; |
||
42 | |||
43 | /** @var Queue */ |
||
44 | private $router; |
||
45 | |||
46 | /** @var DescriptorAbstract */ |
||
47 | private $descriptor; |
||
48 | |||
49 | /** @var Collection */ |
||
50 | private $elementCollection; |
||
51 | |||
52 | /** |
||
53 | * Registers the router queue with this pass. |
||
54 | */ |
||
55 | 5 | public function __construct(Queue $router) |
|
56 | { |
||
57 | 5 | $this->router = $router; |
|
58 | 5 | } |
|
59 | |||
60 | 1 | public function getDescription(): string |
|
61 | { |
||
62 | 1 | return 'Resolve @link and @see tags in descriptions'; |
|
63 | } |
||
64 | |||
65 | /** |
||
66 | * Iterates through each element in the project and replaces its inline @see and @link tag with a markdown |
||
67 | * representation. |
||
68 | */ |
||
69 | 4 | public function execute(ProjectDescriptor $project): void |
|
70 | { |
||
71 | /** @var Collection|DescriptorAbstract[] $elementCollection */ |
||
72 | 4 | $this->elementCollection = $project->getIndexes()->get('elements'); |
|
73 | |||
74 | 4 | foreach ($this->elementCollection as $descriptor) { |
|
75 | 4 | $this->resolveSeeAndLinkTags($descriptor); |
|
76 | } |
||
77 | 4 | } |
|
78 | |||
79 | /** |
||
80 | * Resolves all @see and @link tags in the description of the given descriptor to their markdown representation. |
||
81 | * |
||
82 | * @uses self::resolveTag() |
||
83 | */ |
||
84 | 4 | private function resolveSeeAndLinkTags(DescriptorAbstract $descriptor): void |
|
85 | { |
||
86 | // store descriptor to use it in the resolveTag method |
||
87 | 4 | $this->descriptor = $descriptor; |
|
88 | |||
89 | 4 | $descriptor->setDescription( |
|
90 | 4 | preg_replace_callback( |
|
91 | 4 | self::REGEX_INLINE_LINK_OR_SEE_TAG, |
|
92 | 4 | [$this, 'resolveTag'], |
|
93 | 4 | $descriptor->getDescription() |
|
94 | ) |
||
95 | ); |
||
96 | 4 | } |
|
97 | |||
98 | /** |
||
99 | * Resolves an individual tag, indicated by the results of the Regex used to extract tags. |
||
100 | * |
||
101 | * @param string[] $match |
||
102 | * @return string|string[] |
||
103 | */ |
||
104 | 2 | private function resolveTag(array $match) |
|
105 | { |
||
106 | 2 | $tagReflector = $this->createLinkOrSeeTagFromRegexMatch($match); |
|
107 | 2 | if (!$tagReflector instanceof See && !$tagReflector instanceof Link) { |
|
108 | return $match; |
||
109 | } |
||
110 | |||
111 | 2 | $link = $this->getLinkText($tagReflector); |
|
112 | 2 | $description = (string) $tagReflector->getDescription(); |
|
113 | |||
114 | 2 | if ($this->isUrl($link)) { |
|
115 | return $this->generateMarkdownLink($link, $description ?: $link); |
||
116 | } |
||
117 | |||
118 | 2 | $link = $this->resolveQsen($link); |
|
119 | 2 | $element = $this->findElement($link); |
|
120 | 2 | if (!$element) { |
|
121 | 1 | return (string) $link; |
|
122 | } |
||
123 | |||
124 | 1 | return $this->resolveElement($element, $link, $description); |
|
125 | } |
||
126 | |||
127 | /** |
||
128 | * Determines if the given link string represents a URL by checking if it is prefixed with a URI scheme. |
||
129 | */ |
||
130 | 2 | private function isUrl(string $link): bool |
|
131 | { |
||
132 | 2 | return (bool) preg_match('/^[\w]+:\/\/.+$/', $link); |
|
133 | } |
||
134 | |||
135 | /** |
||
136 | * Checks if the link represents a Fully Qualified Structural Element Name. |
||
137 | * |
||
138 | * @param Fqsen|string $link |
||
139 | */ |
||
140 | 2 | private function isFqsen($link): bool |
|
141 | { |
||
142 | 2 | return $link instanceof Fqsen; |
|
143 | } |
||
144 | |||
145 | /** |
||
146 | * Creates a Tag Reflector from the given array of tag line, tag name and tag content. |
||
147 | * |
||
148 | * @param string[] $match |
||
149 | */ |
||
150 | 2 | private function createLinkOrSeeTagFromRegexMatch(array $match): Tag |
|
151 | { |
||
152 | 2 | list($completeMatch, $tagName, $tagContent) = $match; |
|
0 ignored issues
–
show
|
|||
153 | |||
154 | 2 | $fqsenResolver = new FqsenResolver(); |
|
155 | 2 | $tagFactory = new StandardTagFactory($fqsenResolver); |
|
156 | 2 | $descriptionFactory = new DescriptionFactory($tagFactory); |
|
157 | 2 | $tagFactory->addService($descriptionFactory); |
|
158 | 2 | $tagFactory->addService(new TypeResolver($fqsenResolver)); |
|
159 | |||
160 | switch ($tagName) { |
||
161 | 2 | case 'see': |
|
162 | 2 | return See::create($tagContent, $fqsenResolver, $descriptionFactory, $this->createDocBlockContext()); |
|
163 | case 'link': |
||
164 | return Link::create($tagContent, $descriptionFactory, $this->createDocBlockContext()); |
||
165 | } |
||
166 | } |
||
167 | |||
168 | /** |
||
169 | * Resolves a QSEN to a FQSEN. |
||
170 | * |
||
171 | * If a relative QSEN is provided then this method will attempt to resolve it given the current namespace and |
||
172 | * namespace aliases. |
||
173 | * |
||
174 | * @param Fqsen|string $link |
||
175 | * @return Fqsen|string |
||
176 | */ |
||
177 | 2 | private function resolveQsen($link) |
|
178 | { |
||
179 | 2 | if (!$this->isFqsen($link)) { |
|
180 | 2 | return $link; |
|
181 | } |
||
182 | |||
183 | return $link; |
||
184 | } |
||
185 | |||
186 | /** |
||
187 | * Generates a Markdown link to the given Descriptor or returns the link text if no route to the Descriptor could |
||
188 | * be matched. |
||
189 | * |
||
190 | * @param Fqsen|string $link |
||
191 | */ |
||
192 | 1 | private function resolveElement(DescriptorAbstract $element, $link, ?string $description = null): string |
|
193 | { |
||
194 | 1 | $rule = $this->router->match($element); |
|
195 | |||
196 | 1 | if ($rule) { |
|
197 | 1 | $url = '..' . $rule->generate($element); |
|
198 | 1 | $link = $this->generateMarkdownLink($url, $description ?: (string) $link); |
|
199 | } |
||
200 | |||
201 | 1 | return $link; |
|
202 | } |
||
203 | |||
204 | /** |
||
205 | * Returns the link for the given reflector. |
||
206 | * |
||
207 | * Because the link tag and the see tag have different methods to acquire the link text we abstract that into this |
||
208 | * method. |
||
209 | */ |
||
210 | 2 | private function getLinkText(Tag $tagReflector): ?string |
|
211 | { |
||
212 | 2 | if ($tagReflector instanceof See) { |
|
213 | 2 | return (string) $tagReflector->getReference(); |
|
214 | } |
||
215 | |||
216 | if ($tagReflector instanceof Link) { |
||
217 | return (string) $tagReflector->getLink(); |
||
218 | } |
||
219 | |||
220 | return null; |
||
221 | } |
||
222 | |||
223 | /** |
||
224 | * Tries to find an element with the given FQSEN in the elements listing for this project. |
||
225 | * |
||
226 | * @param Fqsen|string $fqsen |
||
227 | */ |
||
228 | 2 | private function findElement($fqsen): ?DescriptorAbstract |
|
229 | { |
||
230 | 2 | return $this->elementCollection[(string) $fqsen] ?? null; |
|
231 | } |
||
232 | |||
233 | /** |
||
234 | * Creates a DocBlock context containing the namespace and aliases for the current descriptor. |
||
235 | */ |
||
236 | 2 | private function createDocBlockContext(): Context |
|
237 | { |
||
238 | 2 | $file = $this->descriptor->getFile(); |
|
239 | 2 | $namespaceAliases = $file ? $file->getNamespaceAliases()->getAll() : []; |
|
240 | 2 | foreach ($namespaceAliases as $alias => $fqsen) { |
|
241 | 2 | $namespaceAliases[$alias] = (string) $fqsen; |
|
242 | } |
||
243 | |||
244 | 2 | return new Context((string) $this->descriptor->getNamespace(), $namespaceAliases); |
|
245 | } |
||
246 | |||
247 | /** |
||
248 | * Generates a Markdown-formatted string representing a link with a description. |
||
249 | * |
||
250 | * @param Fqsen|string $link |
||
251 | */ |
||
252 | 1 | private function generateMarkdownLink($link, string $description): string |
|
253 | { |
||
254 | 1 | return '[' . $description . '](' . (string) $link . ')'; |
|
255 | } |
||
256 | } |
||
257 |
This checks looks for assignemnts to variables using the
list(...)
function, where not all assigned variables are subsequently used.Consider the following code example.
Only the variables
$a
and$c
are used. There was no need to assign$b
.Instead, the list call could have been.