Passed
Push — master ( 458ee2...f834dc )
by Ryan
17:46 queued 02:16
created

Atom::getSingle()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 7
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 4
nc 1
nop 3
dl 0
loc 7
rs 9.4285
c 0
b 0
f 0
1
<?php
2
/**
3
 * Copyright (c) 2017–2018 Ryan Parman <http://ryanparman.com>.
4
 * Copyright (c) 2017–2018 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 SimplePie\Configuration as C;
15
use SimplePie\Mixin as Tr;
16
use SimplePie\Type as T;
17
use stdClass;
18
19
/**
20
 * Support for the Atom 1.0 grammar.
21
 *
22
 * @see https://tools.ietf.org/html/rfc4287
23
 * @see https://www.w3.org/wiki/Atom
24
 */
25
class Atom extends AbstractXmlMiddleware implements XmlInterface, C\SetLoggerInterface
26
{
27
    use Tr\LoggerTrait;
28
29
    /**
30
     * {@inheritdoc}
31
     */
32
    public function __invoke(stdClass $feedRoot, string $namespaceAlias, DOMXPath $xpath): void
33
    {
34
        // lang (single, scalar)
35
        $this->addArrayProperty($feedRoot, 'lang');
36
        $xq = $xpath->query($this->applyNsToQuery('/%s:feed[attribute::xml:lang][1]/@xml:lang', $namespaceAlias));
37
38
        $feedRoot->lang[$namespaceAlias] = ($xq->length > 0)
39
            ? T\Node::factory((string) $xq->item(0)->nodeValue)
40
            : null;
41
42
        $this->getSingleScalarTypes($feedRoot, $namespaceAlias, $xpath);
43
        $this->getSingleComplexTypes($feedRoot, $namespaceAlias, $xpath);
44
        $this->getMultipleComplexTypes($feedRoot, $namespaceAlias, $xpath);
45
    }
46
47
    /**
48
     * {@inheritdoc}
49
     *
50
     * Supports valid and invalid variations.
51
     *
52
     * * http://www.w3.org/2005/Atom
53
     * * http://www.w3.org/2005/Atom/
54
     * * https://www.w3.org/2005/Atom
55
     * * https://www.w3.org/2005/Atom/
56
     */
57
    public function getSupportedNamespaces(): array
58
    {
59
        return [
60
            'http://www.w3.org/2005/Atom'              => 'atom10',
61
            '/https?:\/\/www\.w3\.org\/2005\/Atom\/?/' => 'atom10',
62
        ];
63
    }
64
65
    /**
66
     * Fetches elements with a single, scalar value.
67
     *
68
     * @param stdClass $feedRoot       The root of the feed. This will be written-to when the parsing middleware runs.
69
     * @param string   $namespaceAlias The preferred namespace alias for a given XML namespace URI. Should be the result
70
     *                                 of a call to `SimplePie\Util\Ns`.
71
     * @param DOMXPath $xpath          The `DOMXPath` object with this middleware's namespace alias applied.
72
     */
73
    protected function getSingleScalarTypes(stdClass $feedRoot, string $namespaceAlias, DOMXPath $xpath): void
74
    {
75
        foreach ([
76
            'icon',
77
            'id',
78
            'logo',
79
            'published',
80
            'rights',
81
            'subtitle',
82
            'summary',
83
            'title',
84
            'updated',
85
        ] as $nodeName) {
86
            $this->addArrayProperty($feedRoot, $nodeName);
87
            $query = $this->generateQuery($namespaceAlias, 'feed', $nodeName);
88
            $this->getLogger()->debug(\sprintf('%s is running an XPath query:', __CLASS__), [$query]);
89
90
            $feedRoot->{$nodeName}[$namespaceAlias] = $this->handleSingleNode(static function () use ($xpath, $query) {
91
                return $xpath->query($query);
92
            });
93
        }
94
    }
95
96
    /**
97
     * Fetches elements with a single, complex value.
98
     *
99
     * @param stdClass $feedRoot       The root of the feed. This will be written-to when the parsing middleware runs.
100
     * @param string   $namespaceAlias The preferred namespace alias for a given XML namespace URI. Should be the result
101
     *                                 of a call to `SimplePie\Util\Ns`.
102
     * @param DOMXPath $xpath          The `DOMXPath` object with this middleware's namespace alias applied.
103
     */
104
    protected function getSingleComplexTypes(stdClass $feedRoot, string $namespaceAlias, DOMXPath $xpath): void
105
    {
106
        foreach ([
107
            'author' => T\Person::class,
108
            'generator' => T\Generator::class,
109
        ] as $name => $class) {
110
            $this->addArrayProperty($feedRoot, $name);
111
            $query = $this->generateQuery($namespaceAlias, 'feed', $name);
112
            $this->getLogger()->debug(\sprintf('%s is running an XPath query:', __CLASS__), [$query]);
113
            $xq = $xpath->query($query);
114
115
            $feedRoot->{$name}[$namespaceAlias] = ($xq->length > 0)
116
                ? new $class($xq->item(0), $this->getLogger())
117
                : null;
118
        }
119
    }
120
121
    /**
122
     * Fetches elements with a multiple, complex values.
123
     *
124
     * @param stdClass $feedRoot       The root of the feed. This will be written-to when the parsing middleware runs.
125
     * @param string   $namespaceAlias The preferred namespace alias for a given XML namespace URI. Should be the result
126
     *                                 of a call to `SimplePie\Util\Ns`.
127
     * @param DOMXPath $xpath          The `DOMXPath` object with this middleware's namespace alias applied.
128
     */
129
    protected function getMultipleComplexTypes(stdClass $feedRoot, string $namespaceAlias, DOMXPath $xpath): void
130
    {
131
        foreach ([
132
            'category' => T\Category::class,
133
            'contributor' => T\Person::class,
134
            'link' => T\Link::class,
135
            'entry' => T\Entry::class,
136
        ] as $name => $class) {
137
            $this->addArrayProperty($feedRoot, $name);
138
            $query = $this->generateQuery($namespaceAlias, 'feed', $name);
139
            $this->getLogger()->debug(\sprintf('%s is running an XPath query:', __CLASS__), [$query]);
140
            $xq = $xpath->query($query);
141
142
            $feedRoot->{$name}[$namespaceAlias] = [];
143
144
            foreach ($xq as $result) {
145
                $feedRoot->{$name}[$namespaceAlias][] = new $class($result, $this->getLogger());
146
            }
147
        }
148
    }
149
}
150