Passed
Push — master ( bf1af5...e52ce1 )
by Ryan
14:07
created

Feed::getHandler()   C

Complexity

Conditions 9
Paths 9

Size

Total Lines 22
Code Lines 18

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 9
eloc 18
nc 9
nop 2
dl 0
loc 22
rs 6.412
c 0
b 0
f 0
1
<?php
2
/**
3
 * Copyright (c) 2017 Ryan Parman <http://ryanparman.com>.
4
 * Copyright (c) 2017 Contributors.
5
 *
6
 * http://opensource.org/licenses/Apache2.0
7
 */
8
9
declare(strict_types=1);
10
11
namespace SimplePie\Type;
12
13
use DateTime;
14
use DateTimeZone;
15
use Psr\Log\NullLogger;
16
use SimplePie\Configuration as C;
17
use SimplePie\Exception\SimplePieException;
18
use SimplePie\Mixin\LoggerTrait;
19
use SimplePie\Parser\Date as DateParser;
20
use stdClass;
21
22
/**
23
 * Represents the top-level of a feed.
24
 */
25
class Feed extends AbstractType implements TypeInterface, C\SetLoggerInterface
26
{
27
    use LoggerTrait;
28
29
    /**
30
     * The root-most node in the feed.
31
     *
32
     * @var stdClass
33
     */
34
    protected $root;
35
36
    /**
37
     * The preferred namespace alias for a given XML namespace URI. Should be
38
     * the result of a call to `SimplePie\Util\Ns`.
39
     *
40
     * @var string
41
     */
42
    protected $namespaceAlias;
43
44
    /**
45
     * The format that should be used when determining how to parse a date from a date string.
46
     *
47
     * @var string
48
     */
49
    protected $createFromFormat;
50
51
    /**
52
     * The preferred timezone to use for date output.
53
     *
54
     * @var string
55
     */
56
    protected $outputTimezone;
57
58
    /**
59
     * Constructs a new instance of this class.
60
     *
61
     * @param string $namespaceAlias [description]
62
     */
63
    public function __construct(string $namespaceAlias)
64
    {
65
        $this->root           = new stdClass();
66
        $this->logger         = new NullLogger();
67
        $this->namespaceAlias = $namespaceAlias;
68
    }
69
70
    /**
71
     * Proxy method which forwards requests to an underlying handler.
72
     *
73
     * @param string $nodeName The name of the method being called.
74
     * @param array  $args     Any arguments passed into that method.
75
     *
76
     * @return mixed
77
     *
78
     * @codingStandardsIgnoreStart
79
     *
80
     * @method \DateTime getPublished(?string $namespaceAlias = null) Indicates an instant-in-time associated with an event early in the life-cycle of the entry.
81
     * @method \DateTime getUpdated(?string $namespaceAlias = null) Indicates the most recent instant-in-time when an entry or feed was modified in a way the publisher considers significant. Therefore, not all modifications necessarily result in a changed value.
82
     * @method SimplePie\Type\Node getId(?string $namespaceAlias = null) Conveys a permanent, universally unique identifier for an entry or feed.
83
     * @method SimplePie\Type\Node getLang(?string $namespaceAlias = null) Indicates the natural language for the element and its descendents.
84
     * @method SimplePie\Type\Node getRights(?string $namespaceAlias = null) Conveys information about rights held in and over an entry or feed.
85
     * @method SimplePie\Type\Node getSubtitle(?string $namespaceAlias = null) Conveys a human-readable description or subtitle for a feed.
86
     * @method SimplePie\Type\Node getSummary(?string $namespaceAlias = null) Conveys a short summary, abstract, or excerpt of an entry.
87
     * @method SimplePie\Type\Node getTitle(?string $namespaceAlias = null) Conveys a human-readable title for an entry or feed.
88
     * @method SimplePie\Type\Generator getGenerator(?string $namespaceAlias = null) Identifies the agent used to generate a feed, for debugging and other purposes.
89
     *
90
     * @codingStandardsIgnoreEnd
91
     */
92
    public function __call(string $nodeName, array $args)
93
    {
94
        // Make sure we have *something*
95
        if (empty($args)) {
96
            $args[0] = null;
97
        }
98
99
        // Strip `get` from the start of the node name.
100
        if ('get' === \mb_substr($nodeName, 0, 3)) {
101
            $nodeName = \lcfirst(\mb_substr($nodeName, 3));
102
        }
103
104
        $nodeName = $this->getAlias($nodeName);
105
106
        return $this->getHandler($nodeName, $args);
107
    }
108
109
    /**
110
     * Allows the user to help the date parser by providing the format of the datestamp in the feed.
111
     *
112
     * This will be passed into `DateTime::createFromFormat()` at parse-time.
113
     *
114
     * @param string $createFromFormat The format of the datestamp in the feed.
115
     *
116
     * @return self
117
     *
118
     * @see http://php.net/manual/en/datetime.createfromformat.php
119
     */
120
    public function setDateFormat(string $createFromFormat): self
121
    {
122
        $this->createFromFormat = $createFromFormat;
123
124
        return $this;
125
    }
126
127
    /**
128
     * Set the preferred output timezone.
129
     *
130
     * This calculation is performed on a _best-effort_ basis and is not guaranteed. Factors which may affect the
131
     * calculation include:
132
     *
133
     * * the version of glibc/musl that your OS relies on
134
     * * the freshness of the timestamp data your OS relies on
135
     * * the format of the datestamp inside of the feed and PHP's ability to parse it
136
     *
137
     * @param string $timezone The timezone identifier to use. Must be compatible with `DateTimeZone`. The default
138
     *                         value is `UTC`.
139
     *
140
     * @return self
141
     */
142
    public function setOutputTimezone(string $timezone = 'UTC'): self
143
    {
144
        $this->outputTimezone = $timezone;
145
146
        return $this;
147
    }
148
149
    /**
150
     * Retrieves nodes that are simple scalars, and there are only one allowed value.
151
     *
152
     * @param string      $nodeName       The name of the tree node to retrieve. Available tree nodes can be viewed by
153
     *                                    looking at the response from `getRoot()`.
154
     * @param string|null $namespaceAlias The XML namespace alias to apply.
155
     *
156
     * @return Node
157
     */
158
    public function getScalarSingleValue(string $nodeName, ?string $namespaceAlias = null): Node
159
    {
160
        $alias = $namespaceAlias ?? $this->namespaceAlias;
161
162
        if (isset($this->getRoot()->{$nodeName}[$alias])) {
163
            return $this->getRoot()->{$nodeName}[$alias];
164
        }
165
166
        return new Node();
167
    }
168
169
    //--------------------------------------------------------------------------
170
    // SINGLE COMPLEX VALUES
171
172
    public function getGenerator(?string $namespaceAlias = null): Generator
173
    {
174
        $alias = $namespaceAlias ?? $this->namespaceAlias;
175
176
        if (isset($this->getRoot()->generator[$alias])) {
177
            return $this->getRoot()->generator[$alias];
178
        }
179
180
        return new Generator();
181
    }
182
183
    public function getAuthor(?string $namespaceAlias = null): Person
184
    {
185
        $alias = $namespaceAlias ?? $this->namespaceAlias;
186
187
        if (isset($this->getRoot()->author[$alias])) {
188
            return $this->getRoot()->author[$alias];
189
        }
190
191
        return new Person();
192
    }
193
194
    //--------------------------------------------------------------------------
195
    // MULTIPLE COMPLEX VALUES
196
197
    public function getContributors(?string $namespaceAlias = null): iterable
198
    {
199
        $alias = $namespaceAlias ?? $this->namespaceAlias;
200
201
        if (isset($this->getRoot()->contributor[$alias])) {
202
            return $this->getRoot()->contributor[$alias];
203
        }
204
205
        return [];
206
    }
207
208
    public function getItems(): void
209
    {
210
    }
211
212
    //--------------------------------------------------------------------------
213
    // INTERNAL
214
215
    /**
216
     * Retrieve the root-most node in the feed.
217
     *
218
     * @return stdClass
219
     */
220
    public function getRoot(): stdClass
221
    {
222
        return $this->root;
223
    }
224
225
    /**
226
     * Finds the common internal alias for a given method name.
227
     *
228
     * @param string $nodeName The name of the method being called.
229
     *
230
     * @return string
231
     */
232
    protected function getAlias(string $nodeName): string
233
    {
234
        switch ($nodeName) {
235
            case 'language':
236
                return 'lang';
237
238
            case 'pubDate':
239
            case 'publishedDate':
240
                return 'published';
241
242
            default:
243
                return $nodeName;
244
        }
245
    }
246
247
    /**
248
     * Get the correct handler for a whitelisted method name.
249
     *
250
     * @param string $nodeName The name of the method being called.
251
     * @param array  $args     Any arguments passed into that method.
252
     *
253
     * @throws SimplePieException
254
     *
255
     * @return mixed
256
     */
257
    protected function getHandler(string $nodeName, array $args)
258
    {
259
        switch ($nodeName) {
260
            case 'id':
261
            case 'lang':
262
            case 'rights':
263
            case 'subtitle':
264
            case 'summary':
265
            case 'title':
266
                return $this->getScalarSingleValue($nodeName, $args[0]);
267
268
            case 'published':
269
            case 'updated':
270
                return (new DateParser(
271
                    $this->getScalarSingleValue($nodeName, $args[0])->getValue(),
272
                    $this->outputTimezone,
273
                    $this->createFromFormat
274
                ))->getDateTime();
275
276
            default:
277
                throw new SimplePieException(
278
                    \sprintf('%s is an unresolvable method.')
279
                );
280
        }
281
    }
282
}
283