1 | <?php |
||||
2 | /** |
||||
3 | * Copyright (c) 2017–2019 Ryan Parman <http://ryanparman.com>. |
||||
4 | * Copyright (c) 2017–2019 Contributors. |
||||
5 | * |
||||
6 | * http://opensource.org/licenses/Apache2.0 |
||||
7 | */ |
||||
8 | |||||
9 | declare(strict_types=1); |
||||
10 | |||||
11 | namespace SimplePie\Middleware\Xml; |
||||
12 | |||||
13 | use DOMXPath; |
||||
14 | use ReflectionClass; |
||||
15 | use SimplePie\Configuration as C; |
||||
16 | use SimplePie\Mixin as Tr; |
||||
17 | use SimplePie\Type as T; |
||||
18 | use stdClass; |
||||
19 | |||||
20 | /** |
||||
21 | * Support for the Atom 1.0 grammar. |
||||
22 | * |
||||
23 | * @see https://tools.ietf.org/html/rfc4287 |
||||
24 | * @see https://www.w3.org/wiki/Atom |
||||
25 | */ |
||||
26 | class Atom extends AbstractXmlMiddleware implements C\SetLoggerInterface, XmlInterface |
||||
27 | { |
||||
28 | use Tr\LoggerTrait; |
||||
0 ignored issues
–
show
|
|||||
29 | |||||
30 | /** |
||||
31 | * {@inheritdoc} |
||||
32 | */ |
||||
33 | 560 | public function __invoke(stdClass $feedRoot, string $namespaceAlias, DOMXPath $xpath): void |
|||
34 | { |
||||
35 | // Top-level feed |
||||
36 | 560 | $path = ['feed']; |
|||
37 | |||||
38 | 560 | $this->getNodeAttributes($feedRoot, $namespaceAlias, $xpath, $path); |
|||
39 | |||||
40 | $feedFallback = [ |
||||
41 | 560 | 'base' => $feedRoot->base[$namespaceAlias]->getNode(), |
|||
42 | 560 | 'lang' => $feedRoot->lang[$namespaceAlias]->getNode(), |
|||
43 | ]; |
||||
44 | |||||
45 | 560 | $this->getSingleScalarTypes($feedRoot, $namespaceAlias, $xpath, $path, $feedFallback); |
|||
46 | 560 | $this->getSingleComplexTypes($feedRoot, $namespaceAlias, $xpath, $path); |
|||
47 | 560 | $this->getMultipleComplexTypes($feedRoot, $namespaceAlias, $xpath, $path); |
|||
48 | |||||
49 | // <entry> element |
||||
50 | 560 | $path = ['feed', 'entry']; |
|||
51 | |||||
52 | 560 | foreach ($feedRoot->entry[$namespaceAlias] as $i => &$entry) { |
|||
53 | 220 | $cpath = $path; |
|||
54 | 220 | $cpath[] = $i; |
|||
55 | |||||
56 | $feedFallback = [ |
||||
57 | 220 | 'base' => $feedRoot->base[$namespaceAlias]->getNode(), |
|||
58 | 220 | 'lang' => $feedRoot->lang[$namespaceAlias]->getNode(), |
|||
59 | ]; |
||||
60 | |||||
61 | 220 | $this->getNodeAttributes($entry, $namespaceAlias, $xpath, $cpath, $feedFallback); |
|||
62 | |||||
63 | $entryFallback = [ |
||||
64 | 220 | 'base' => $entry->base[$namespaceAlias]->getNode(), |
|||
65 | 220 | 'lang' => $entry->lang[$namespaceAlias]->getNode(), |
|||
66 | ]; |
||||
67 | |||||
68 | 220 | $this->getSingleScalarTypes($entry, $namespaceAlias, $xpath, $cpath, $entryFallback); |
|||
69 | 220 | $this->getSingleComplexTypes($entry, $namespaceAlias, $xpath, $cpath); |
|||
70 | 220 | $this->getMultipleComplexTypes($entry, $namespaceAlias, $xpath, $cpath); |
|||
71 | } |
||||
72 | 560 | } |
|||
73 | |||||
74 | /** |
||||
75 | * {@inheritdoc} |
||||
76 | * |
||||
77 | * Supports valid and invalid variations. |
||||
78 | * |
||||
79 | * * http://www.w3.org/2005/Atom |
||||
80 | * * http://www.w3.org/2005/Atom/ |
||||
81 | * * https://www.w3.org/2005/Atom |
||||
82 | * * https://www.w3.org/2005/Atom/ |
||||
83 | */ |
||||
84 | 560 | public function getSupportedNamespaces(): array |
|||
85 | { |
||||
86 | return [ |
||||
87 | 560 | 'http://www.w3.org/2005/Atom' => 'atom10', |
|||
88 | '/https?:\/\/www\.w3\.org\/2005\/Atom\/?/' => 'atom10', |
||||
89 | ]; |
||||
90 | } |
||||
91 | |||||
92 | /** |
||||
93 | * Fetches attributes with a single, scalar value, on elements. |
||||
94 | * |
||||
95 | * @param stdClass $feedRoot The root of the feed. This will be written-to when the parsing middleware runs. |
||||
96 | * @param string $namespaceAlias The preferred namespace alias for a given XML namespace URI. Should be the result |
||||
97 | * of a call to `SimplePie\Util\Ns`. |
||||
98 | * @param DOMXPath $xpath The `DOMXPath` object with this middleware's namespace alias applied. |
||||
99 | * @param array $path The path of the XML traversal. Should begin with `<feed>` or `<channel>`, |
||||
100 | * then `<entry>` or `<item>`. |
||||
101 | * @param array $fallback An array of attributes for default XML attributes. The default value is an |
||||
102 | * empty array. |
||||
103 | * |
||||
104 | * @phpcs:disable Generic.Functions.OpeningFunctionBraceBsdAllman.BraceOnSameLine |
||||
105 | */ |
||||
106 | 560 | protected function getNodeAttributes( |
|||
107 | object $feedRoot, |
||||
108 | string $namespaceAlias, |
||||
109 | DOMXPath $xpath, |
||||
110 | array $path, |
||||
111 | array $fallback = [] |
||||
112 | ): void { |
||||
113 | // @phpcs:enable |
||||
114 | |||||
115 | $attrs = [ |
||||
116 | 560 | 'base' => '@xml:base', |
|||
117 | 'lang' => '@xml:lang', |
||||
118 | ]; |
||||
119 | |||||
120 | // Used for traversing up the tree for inheritance |
||||
121 | 560 | $pathMinusLastBit = $path; |
|||
122 | 560 | \array_pop($pathMinusLastBit); |
|||
123 | |||||
124 | 560 | foreach ($attrs as $nodeName => $searchName) { |
|||
125 | 560 | $query = $this->generateQuery($namespaceAlias, \array_merge($path, [$searchName])); |
|||
126 | 560 | $xq = $xpath->query($query); |
|||
127 | 560 | $this->addArrayProperty($feedRoot, $nodeName); |
|||
128 | 560 | $this->getLogger()->debug(\sprintf('%s is running an XPath query:', __CLASS__), [$query]); |
|||
129 | |||||
130 | 560 | $feedRoot->{$nodeName}[$namespaceAlias] = (false !== $xq && $xq->length > 0) |
|||
131 | 68 | ? new T\Node($xq->item(0)) |
|||
132 | 560 | : new T\Node($this->get($fallback, $nodeName)); |
|||
0 ignored issues
–
show
$this->get($fallback, $nodeName) of type string is incompatible with the type DOMNode|null expected by parameter $node of SimplePie\Type\Node::__construct() .
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
![]() |
|||||
133 | } |
||||
134 | 560 | } |
|||
135 | |||||
136 | /** |
||||
137 | * Fetches elements with a single, scalar value. |
||||
138 | * |
||||
139 | * @param stdClass $feedRoot The root of the feed. This will be written-to when the parsing middleware runs. |
||||
140 | * @param string $namespaceAlias The preferred namespace alias for a given XML namespace URI. Should be the result |
||||
141 | * of a call to `SimplePie\Util\Ns`. |
||||
142 | * @param DOMXPath $xpath The `DOMXPath` object with this middleware's namespace alias applied. |
||||
143 | * @param array $path The path of the XML traversal. Should begin with `<feed>` or `<channel>`, |
||||
144 | * then `<entry>` or `<item>`. |
||||
145 | * @param array $fallback An array of attributes for default XML attributes. The default value is an |
||||
146 | * empty array. |
||||
147 | * |
||||
148 | * @phpcs:disable Generic.Functions.OpeningFunctionBraceBsdAllman.BraceOnSameLine |
||||
149 | */ |
||||
150 | 560 | protected function getSingleScalarTypes( |
|||
151 | object $feedRoot, |
||||
152 | string $namespaceAlias, |
||||
153 | DOMXPath $xpath, |
||||
154 | array $path, |
||||
155 | array $fallback = [] |
||||
156 | ): void { |
||||
157 | // @phpcs:enable |
||||
158 | |||||
159 | 560 | $cpath = $path; |
|||
160 | 560 | $nodes = []; |
|||
161 | |||||
162 | 560 | if (\is_int(\end($cpath))) { |
|||
163 | 220 | \array_pop($cpath); |
|||
164 | } |
||||
165 | |||||
166 | 560 | if ('feed' === \end($cpath)) { |
|||
167 | $nodes = [ |
||||
168 | 560 | 'icon', |
|||
169 | 'id', |
||||
170 | 'logo', |
||||
171 | 'published', |
||||
172 | 'rights', |
||||
173 | 'subtitle', |
||||
174 | 'summary', |
||||
175 | 'title', |
||||
176 | 'updated', |
||||
177 | ]; |
||||
178 | 220 | } elseif ('entry' === \end($cpath)) { |
|||
179 | $nodes = [ |
||||
180 | 220 | 'content', |
|||
181 | 'id', |
||||
182 | 'published', |
||||
183 | 'rights', |
||||
184 | 'summary', |
||||
185 | 'title', |
||||
186 | 'updated', |
||||
187 | ]; |
||||
188 | } |
||||
189 | |||||
190 | 560 | foreach ($nodes as $nodeName) { |
|||
191 | 560 | $query = $this->generateQuery($namespaceAlias, \array_merge($path, [$nodeName])); |
|||
192 | 560 | $xq = $xpath->query($query); |
|||
193 | 560 | $this->addArrayProperty($feedRoot, $nodeName); |
|||
194 | 560 | $this->getLogger()->debug(\sprintf('%s is running an XPath query:', __CLASS__), [$query]); |
|||
195 | |||||
196 | 560 | $feedRoot->{$nodeName}[$namespaceAlias] = (false !== $xq && $xq->length > 0) |
|||
197 | 479 | ? new T\Node($xq->item(0), $fallback) |
|||
198 | 560 | : new T\Node(); |
|||
199 | } |
||||
200 | 560 | } |
|||
201 | |||||
202 | /** |
||||
203 | * Fetches elements with a single, complex value. |
||||
204 | * |
||||
205 | * @param stdClass $feedRoot The root of the feed. This will be written-to when the parsing middleware runs. |
||||
206 | * @param string $namespaceAlias The preferred namespace alias for a given XML namespace URI. Should be the result |
||||
207 | * of a call to `SimplePie\Util\Ns`. |
||||
208 | * @param DOMXPath $xpath The `DOMXPath` object with this middleware's namespace alias applied. |
||||
209 | * @param array $path The path of the XML traversal. Should begin with `<feed>` or `<channel>`, |
||||
210 | * then `<entry>` or `<item>`. |
||||
211 | * |
||||
212 | * @phpcs:disable Generic.Functions.OpeningFunctionBraceBsdAllman.BraceOnSameLine |
||||
213 | */ |
||||
214 | 560 | protected function getSingleComplexTypes( |
|||
215 | object $feedRoot, |
||||
216 | string $namespaceAlias, |
||||
217 | DOMXPath $xpath, |
||||
218 | array $path |
||||
219 | ): void { |
||||
220 | // @phpcs:enable |
||||
221 | |||||
222 | 560 | $cpath = $path; |
|||
223 | 560 | $nodes = []; |
|||
224 | |||||
225 | 560 | if (\is_int(\end($cpath))) { |
|||
226 | 220 | \array_pop($cpath); |
|||
227 | } |
||||
228 | |||||
229 | 560 | if ('feed' === \end($cpath)) { |
|||
230 | $nodes = [ |
||||
231 | 560 | 'generator' => T\Generator::class, |
|||
232 | ]; |
||||
233 | } |
||||
234 | |||||
235 | 560 | foreach ($nodes as $name => $class) { |
|||
236 | 560 | $query = $this->generateQuery($namespaceAlias, \array_merge($path, [$name])); |
|||
237 | 560 | $xq = $xpath->query($query); |
|||
238 | 560 | $this->addArrayProperty($feedRoot, $name); |
|||
239 | 560 | $this->getLogger()->debug(\sprintf('%s is running an XPath query:', __CLASS__), [$query]); |
|||
240 | |||||
241 | 560 | $feedRoot->{$name}[$namespaceAlias] = (false !== $xq && $xq->length > 0) |
|||
242 | 44 | ? new $class($xq->item(0), $this->getLogger()) |
|||
243 | 516 | : null; |
|||
244 | } |
||||
245 | 560 | } |
|||
246 | |||||
247 | /** |
||||
248 | * Fetches elements with a multiple, complex values. |
||||
249 | * |
||||
250 | * @param stdClass $feedRoot The root of the feed. This will be written-to when the parsing middleware runs. |
||||
251 | * @param string $namespaceAlias The preferred namespace alias for a given XML namespace URI. Should be the result |
||||
252 | * of a call to `SimplePie\Util\Ns`. |
||||
253 | * @param DOMXPath $xpath The `DOMXPath` object with this middleware's namespace alias applied. |
||||
254 | * @param array $path The path of the XML traversal. Should begin with `<feed>` or `<channel>`, |
||||
255 | * then `<entry>` or `<item>`. |
||||
256 | * |
||||
257 | * @phpcs:disable Generic.Functions.OpeningFunctionBraceBsdAllman.BraceOnSameLine |
||||
258 | */ |
||||
259 | 560 | protected function getMultipleComplexTypes( |
|||
260 | object $feedRoot, |
||||
261 | string $namespaceAlias, |
||||
262 | DOMXPath $xpath, |
||||
263 | array $path |
||||
264 | ): void { |
||||
265 | // @phpcs:enable |
||||
266 | |||||
267 | 560 | $cpath = $path; |
|||
268 | 560 | $nodes = []; |
|||
269 | |||||
270 | 560 | if (\is_int(\end($cpath))) { |
|||
271 | 220 | \array_pop($cpath); |
|||
272 | } |
||||
273 | |||||
274 | 560 | if ('feed' === \end($cpath)) { |
|||
275 | $nodes = [ |
||||
276 | 560 | 'author' => T\Person::class, |
|||
277 | 'category' => T\Category::class, |
||||
278 | 'contributor' => T\Person::class, |
||||
279 | 'entry' => T\Entry::class, |
||||
280 | 'link' => T\Link::class, |
||||
281 | ]; |
||||
282 | 220 | } elseif ('entry' === \end($cpath)) { |
|||
283 | $nodes = [ |
||||
284 | 220 | 'author' => T\Person::class, |
|||
285 | 'category' => T\Category::class, |
||||
286 | 'contributor' => T\Person::class, |
||||
287 | 'link' => T\Link::class, |
||||
288 | ]; |
||||
289 | } |
||||
290 | |||||
291 | 560 | foreach ($nodes as $name => $class) { |
|||
292 | 560 | $query = $this->generateQuery($namespaceAlias, \array_merge($path, [$name])); |
|||
293 | 560 | $xq = $xpath->query($query); |
|||
294 | 560 | $this->addArrayProperty($feedRoot, $name); |
|||
295 | 560 | $this->getLogger()->debug(\sprintf('%s is running an XPath query:', __CLASS__), [$query]); |
|||
296 | |||||
297 | 560 | $feedRoot->{$name}[$namespaceAlias] = []; |
|||
298 | |||||
299 | 560 | foreach ($xq as $result) { |
|||
300 | // What kind of class is this? |
||||
301 | 253 | $rclass = (new ReflectionClass($class)) |
|||
302 | 253 | ->newInstanceWithoutConstructor(); |
|||
303 | |||||
304 | 253 | if ($rclass instanceof T\BranchInterface) { |
|||
305 | 220 | $feedRoot->{$name}[$namespaceAlias][] = new $class( |
|||
306 | 220 | $namespaceAlias, |
|||
307 | $result, |
||||
308 | 220 | $this->getLogger() |
|||
309 | ); |
||||
310 | } else { |
||||
311 | 115 | $feedRoot->{$name}[$namespaceAlias][] = new $class( |
|||
312 | 115 | $result, |
|||
313 | 115 | $this->getLogger() |
|||
314 | ); |
||||
315 | } |
||||
316 | } |
||||
317 | } |
||||
318 | 560 | } |
|||
319 | } |
||||
320 |
The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g.
excluded_paths: ["lib/*"]
, you can move it to the dependency path list as follows:For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths