simplepie /
simplepie-ng
| 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
Loading history...
|
|||||
| 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