run:R W Run
DIR
2026-03-11 16:18:52
R W Run
DIR
2026-03-11 16:18:52
R W Run
DIR
2026-03-11 16:18:52
R W Run
DIR
2026-03-11 16:18:52
R W Run
DIR
2026-03-11 16:18:52
R W Run
DIR
2026-03-11 16:18:52
R W Run
1.86 KB
2026-03-11 16:18:52
R W Run
3.17 KB
2026-03-11 16:18:52
R W Run
3.03 KB
2026-03-11 16:18:52
R W Run
2.41 KB
2026-03-11 16:18:52
R W Run
1.67 KB
2026-03-11 16:18:52
R W Run
2.09 KB
2026-03-11 16:18:52
R W Run
31.39 KB
2026-03-11 16:18:52
R W Run
355 By
2026-03-11 16:18:52
R W Run
18.94 KB
2026-03-11 16:18:52
R W Run
8.31 KB
2026-03-11 16:18:52
R W Run
33.99 KB
2026-03-11 16:18:52
R W Run
128.54 KB
2026-03-11 16:18:52
R W Run
16.31 KB
2026-03-11 16:18:52
R W Run
68.16 KB
2026-03-11 16:18:52
R W Run
34.05 KB
2026-03-11 16:18:52
R W Run
1.75 KB
2026-03-11 16:18:52
R W Run
7.71 KB
2026-03-11 16:18:52
R W Run
447 By
2026-03-11 16:18:52
R W Run
2.31 KB
2026-03-11 16:18:52
R W Run
29.64 KB
2026-03-11 16:18:52
R W Run
125.05 KB
2026-03-11 16:18:52
R W Run
23.18 KB
2026-03-11 16:18:52
R W Run
error_log
📄Item.php
1<?php
2
3// SPDX-FileCopyrightText: 2004-2023 Ryan Parman, Sam Sneddon, Ryan McCue
4// SPDX-License-Identifier: BSD-3-Clause
5
6declare(strict_types=1);
7
8namespace SimplePie;
9
10/**
11 * Manages all item-related data
12 *
13 * Used by {@see \SimplePie\SimplePie::get_item()} and {@see \SimplePie\SimplePie::get_items()}
14 *
15 * This class can be overloaded with {@see \SimplePie\SimplePie::set_item_class()}
16 */
17class Item implements RegistryAware
18{
19 /**
20 * Parent feed
21 *
22 * @access private
23 * @var \SimplePie\SimplePie
24 */
25 public $feed;
26
27 /**
28 * Raw data
29 *
30 * @access private
31 * @var array<string, mixed>
32 */
33 public $data = [];
34
35 /**
36 * Registry object
37 *
38 * @see set_registry
39 * @var \SimplePie\Registry
40 */
41 protected $registry;
42
43 /**
44 * @var Sanitize|null
45 */
46 private $sanitize = null;
47
48 /**
49 * Create a new item object
50 *
51 * This is usually used by {@see \SimplePie\SimplePie::get_items} and
52 * {@see \SimplePie\SimplePie::get_item}. Avoid creating this manually.
53 *
54 * @param \SimplePie\SimplePie $feed Parent feed
55 * @param array<string, mixed> $data Raw data
56 */
57 public function __construct(\SimplePie\SimplePie $feed, array $data)
58 {
59 $this->feed = $feed;
60 $this->data = $data;
61 }
62
63 /**
64 * Set the registry handler
65 *
66 * This is usually used by {@see \SimplePie\Registry::create}
67 *
68 * @since 1.3
69 * @param \SimplePie\Registry $registry
70 * @return void
71 */
72 public function set_registry(\SimplePie\Registry $registry)
73 {
74 $this->registry = $registry;
75 }
76
77 /**
78 * Get a string representation of the item
79 *
80 * @return string
81 */
82 public function __toString()
83 {
84 return md5(serialize($this->data));
85 }
86
87 /**
88 * Remove items that link back to this before destroying this object
89 */
90 public function __destruct()
91 {
92 if (!gc_enabled()) {
93 unset($this->feed);
94 }
95 }
96
97 /**
98 * Get data for an item-level element
99 *
100 * This method allows you to get access to ANY element/attribute that is a
101 * sub-element of the item/entry tag.
102 *
103 * See {@see \SimplePie\SimplePie::get_feed_tags()} for a description of the return value
104 *
105 * @since 1.0
106 * @see http://simplepie.org/wiki/faq/supported_xml_namespaces
107 * @param string $namespace The URL of the XML namespace of the elements you're trying to access
108 * @param string $tag Tag name
109 * @return array<array<string, mixed>>|null
110 */
111 public function get_item_tags(string $namespace, string $tag)
112 {
113 if (isset($this->data['child'][$namespace][$tag])) {
114 return $this->data['child'][$namespace][$tag];
115 }
116
117 return null;
118 }
119
120 /**
121 * Get base URL of the item itself.
122 * Returns `<xml:base>` or feed base URL.
123 * Similar to `Item::get_base()` but can safely be used during initialisation methods
124 * such as `Item::get_links()` (`Item::get_base()` and `Item::get_links()` call each-other)
125 * and is not affected by enclosures.
126 *
127 * @param array<string, mixed> $element
128 * @see get_base
129 */
130 private function get_own_base(array $element = []): string
131 {
132 if (!empty($element['xml_base_explicit']) && isset($element['xml_base'])) {
133 return $element['xml_base'];
134 }
135 return $this->feed->get_base();
136 }
137
138 /**
139 * Get the base URL value.
140 * Uses `<xml:base>`, or item link, or enclosure link, or feed base URL.
141 *
142 * @param array<string, mixed> $element
143 * @return string
144 */
145 public function get_base(array $element = [])
146 {
147 if (!empty($element['xml_base_explicit']) && isset($element['xml_base'])) {
148 return $element['xml_base'];
149 }
150 $link = $this->get_permalink();
151 if ($link != null) {
152 return $link;
153 }
154 return $this->feed->get_base($element);
155 }
156
157 /**
158 * Sanitize feed data
159 *
160 * @access private
161 * @see \SimplePie\SimplePie::sanitize()
162 * @param string $data Data to sanitize
163 * @param int-mask-of<SimplePie::CONSTRUCT_*> $type
164 * @param string $base Base URL to resolve URLs against
165 * @return string Sanitized data
166 */
167 public function sanitize(string $data, int $type, string $base = '')
168 {
169 // This really returns string|false but changing encoding is uncommon and we are going to deprecate it, so let’s just lie to PHPStan in the interest of cleaner annotations.
170 return $this->feed->sanitize($data, $type, $base);
171 }
172
173 /**
174 * Get the parent feed
175 *
176 * Note: this may not work as you think for multifeeds!
177 *
178 * @link http://simplepie.org/faq/typical_multifeed_gotchas#missing_data_from_feed
179 * @since 1.0
180 * @return \SimplePie\SimplePie
181 */
182 public function get_feed()
183 {
184 return $this->feed;
185 }
186
187 /**
188 * Get the unique identifier for the item
189 *
190 * This is usually used when writing code to check for new items in a feed.
191 *
192 * Uses `<atom:id>`, `<guid>`, `<dc:identifier>` or the `about` attribute
193 * for RDF. If none of these are supplied (or `$hash` is true), creates an
194 * MD5 hash based on the permalink, title and content.
195 *
196 * @since Beta 2
197 * @param bool $hash Should we force using a hash instead of the supplied ID?
198 * @param string|false $fn User-supplied function to generate an hash
199 * @return string|null
200 */
201 public function get_id(bool $hash = false, $fn = 'md5')
202 {
203 if (!$hash) {
204 if ($return = $this->get_item_tags(\SimplePie\SimplePie::NAMESPACE_ATOM_10, 'id')) {
205 return $this->sanitize($return[0]['data'], \SimplePie\SimplePie::CONSTRUCT_TEXT);
206 } elseif ($return = $this->get_item_tags(\SimplePie\SimplePie::NAMESPACE_ATOM_03, 'id')) {
207 return $this->sanitize($return[0]['data'], \SimplePie\SimplePie::CONSTRUCT_TEXT);
208 } elseif ($return = $this->get_item_tags(\SimplePie\SimplePie::NAMESPACE_RSS_20, 'guid')) {
209 return $this->sanitize($return[0]['data'], \SimplePie\SimplePie::CONSTRUCT_TEXT);
210 } elseif ($return = $this->get_item_tags(\SimplePie\SimplePie::NAMESPACE_DC_11, 'identifier')) {
211 return $this->sanitize($return[0]['data'], \SimplePie\SimplePie::CONSTRUCT_TEXT);
212 } elseif ($return = $this->get_item_tags(\SimplePie\SimplePie::NAMESPACE_DC_10, 'identifier')) {
213 return $this->sanitize($return[0]['data'], \SimplePie\SimplePie::CONSTRUCT_TEXT);
214 } elseif (isset($this->data['attribs'][\SimplePie\SimplePie::NAMESPACE_RDF]['about'])) {
215 return $this->sanitize($this->data['attribs'][\SimplePie\SimplePie::NAMESPACE_RDF]['about'], \SimplePie\SimplePie::CONSTRUCT_TEXT);
216 }
217 }
218 if ($fn === false) {
219 return null;
220 } elseif (!is_callable($fn)) {
221 trigger_error('User-supplied function $fn must be callable', E_USER_WARNING);
222 $fn = 'md5';
223 }
224 return call_user_func(
225 $fn,
226 $this->get_permalink().$this->get_title().$this->get_content()
227 );
228 }
229
230 /**
231 * Get the title of the item
232 *
233 * Uses `<atom:title>`, `<title>` or `<dc:title>`
234 *
235 * @since Beta 2 (previously called `get_item_title` since 0.8)
236 * @return string|null
237 */
238 public function get_title()
239 {
240 if (!isset($this->data['title'])) {
241 if ($return = $this->get_item_tags(\SimplePie\SimplePie::NAMESPACE_ATOM_10, 'title')) {
242 $this->data['title'] = $this->sanitize($return[0]['data'], $this->registry->call(Misc::class, 'atom_10_construct_type', [$return[0]['attribs']]), $this->get_base($return[0]));
243 } elseif ($return = $this->get_item_tags(\SimplePie\SimplePie::NAMESPACE_ATOM_03, 'title')) {
244 $this->data['title'] = $this->sanitize($return[0]['data'], $this->registry->call(Misc::class, 'atom_03_construct_type', [$return[0]['attribs']]), $this->get_base($return[0]));
245 } elseif ($return = $this->get_item_tags(\SimplePie\SimplePie::NAMESPACE_RSS_10, 'title')) {
246 $this->data['title'] = $this->sanitize($return[0]['data'], \SimplePie\SimplePie::CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
247 } elseif ($return = $this->get_item_tags(\SimplePie\SimplePie::NAMESPACE_RSS_090, 'title')) {
248 $this->data['title'] = $this->sanitize($return[0]['data'], \SimplePie\SimplePie::CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
249 } elseif ($return = $this->get_item_tags(\SimplePie\SimplePie::NAMESPACE_RSS_20, 'title')) {
250 $this->data['title'] = $this->sanitize($return[0]['data'], \SimplePie\SimplePie::CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
251 } elseif ($return = $this->get_item_tags(\SimplePie\SimplePie::NAMESPACE_DC_11, 'title')) {
252 $this->data['title'] = $this->sanitize($return[0]['data'], \SimplePie\SimplePie::CONSTRUCT_TEXT);
253 } elseif ($return = $this->get_item_tags(\SimplePie\SimplePie::NAMESPACE_DC_10, 'title')) {
254 $this->data['title'] = $this->sanitize($return[0]['data'], \SimplePie\SimplePie::CONSTRUCT_TEXT);
255 } else {
256 $this->data['title'] = null;
257 }
258 }
259 return $this->data['title'];
260 }
261
262 /**
263 * Get the content for the item
264 *
265 * Prefers summaries over full content , but will return full content if a
266 * summary does not exist.
267 *
268 * To prefer full content instead, use {@see get_content}
269 *
270 * Uses `<atom:summary>`, `<description>`, `<dc:description>` or
271 * `<itunes:subtitle>`
272 *
273 * @since 0.8
274 * @param bool $description_only Should we avoid falling back to the content?
275 * @return string|null
276 */
277 public function get_description(bool $description_only = false)
278 {
279 if (($tags = $this->get_item_tags(\SimplePie\SimplePie::NAMESPACE_ATOM_10, 'summary')) &&
280 ($return = $this->sanitize($tags[0]['data'], $this->registry->call(Misc::class, 'atom_10_construct_type', [$tags[0]['attribs']]), $this->get_base($tags[0])))) {
281 return $return;
282 } elseif (($tags = $this->get_item_tags(\SimplePie\SimplePie::NAMESPACE_ATOM_03, 'summary')) &&
283 ($return = $this->sanitize($tags[0]['data'], $this->registry->call(Misc::class, 'atom_03_construct_type', [$tags[0]['attribs']]), $this->get_base($tags[0])))) {
284 return $return;
285 } elseif (($tags = $this->get_item_tags(\SimplePie\SimplePie::NAMESPACE_RSS_10, 'description')) &&
286 ($return = $this->sanitize($tags[0]['data'], \SimplePie\SimplePie::CONSTRUCT_MAYBE_HTML, $this->get_base($tags[0])))) {
287 return $return;
288 } elseif (($tags = $this->get_item_tags(\SimplePie\SimplePie::NAMESPACE_RSS_20, 'description')) &&
289 ($return = $this->sanitize($tags[0]['data'], \SimplePie\SimplePie::CONSTRUCT_HTML, $this->get_base($tags[0])))) {
290 return $return;
291 } elseif (($tags = $this->get_item_tags(\SimplePie\SimplePie::NAMESPACE_DC_11, 'description')) &&
292 ($return = $this->sanitize($tags[0]['data'], \SimplePie\SimplePie::CONSTRUCT_TEXT))) {
293 return $return;
294 } elseif (($tags = $this->get_item_tags(\SimplePie\SimplePie::NAMESPACE_DC_10, 'description')) &&
295 ($return = $this->sanitize($tags[0]['data'], \SimplePie\SimplePie::CONSTRUCT_TEXT))) {
296 return $return;
297 } elseif (($tags = $this->get_item_tags(\SimplePie\SimplePie::NAMESPACE_ITUNES, 'summary')) &&
298 ($return = $this->sanitize($tags[0]['data'], \SimplePie\SimplePie::CONSTRUCT_HTML, $this->get_base($tags[0])))) {
299 return $return;
300 } elseif (($tags = $this->get_item_tags(\SimplePie\SimplePie::NAMESPACE_ITUNES, 'subtitle')) &&
301 ($return = $this->sanitize($tags[0]['data'], \SimplePie\SimplePie::CONSTRUCT_TEXT))) {
302 return $return;
303 } elseif (($tags = $this->get_item_tags(\SimplePie\SimplePie::NAMESPACE_RSS_090, 'description')) &&
304 ($return = $this->sanitize($tags[0]['data'], \SimplePie\SimplePie::CONSTRUCT_HTML))) {
305 return $return;
306 } elseif (!$description_only) {
307 return $this->get_content(true);
308 }
309
310 return null;
311 }
312
313 /**
314 * Get the content for the item
315 *
316 * Prefers full content over summaries, but will return a summary if full
317 * content does not exist.
318 *
319 * To prefer summaries instead, use {@see get_description}
320 *
321 * Uses `<atom:content>` or `<content:encoded>` (RSS 1.0 Content Module)
322 *
323 * @since 1.0
324 * @param bool $content_only Should we avoid falling back to the description?
325 * @return string|null
326 */
327 public function get_content(bool $content_only = false)
328 {
329 if (($tags = $this->get_item_tags(\SimplePie\SimplePie::NAMESPACE_ATOM_10, 'content')) &&
330 ($return = $this->sanitize($tags[0]['data'], $this->registry->call(Misc::class, 'atom_10_content_construct_type', [$tags[0]['attribs']]), $this->get_base($tags[0])))) {
331 return $return;
332 } elseif (($tags = $this->get_item_tags(\SimplePie\SimplePie::NAMESPACE_ATOM_03, 'content')) &&
333 ($return = $this->sanitize($tags[0]['data'], $this->registry->call(Misc::class, 'atom_03_construct_type', [$tags[0]['attribs']]), $this->get_base($tags[0])))) {
334 return $return;
335 } elseif (($tags = $this->get_item_tags(\SimplePie\SimplePie::NAMESPACE_RSS_10_MODULES_CONTENT, 'encoded')) &&
336 ($return = $this->sanitize($tags[0]['data'], \SimplePie\SimplePie::CONSTRUCT_HTML, $this->get_base($tags[0])))) {
337 return $return;
338 } elseif (!$content_only) {
339 return $this->get_description(true);
340 }
341
342 return null;
343 }
344
345 /**
346 * Get the media:thumbnail of the item
347 *
348 * Uses `<media:thumbnail>`
349 *
350 *
351 * @return array{url: string, height?: string, width?: string, time?: string}|null
352 */
353 public function get_thumbnail()
354 {
355 if (!isset($this->data['thumbnail'])) {
356 if ($return = $this->get_item_tags(\SimplePie\SimplePie::NAMESPACE_MEDIARSS, 'thumbnail')) {
357 $thumbnail = $return[0]['attribs'][''];
358 if (empty($thumbnail['url'])) {
359 $this->data['thumbnail'] = null;
360 } else {
361 $thumbnail['url'] = $this->sanitize($thumbnail['url'], \SimplePie\SimplePie::CONSTRUCT_IRI, $this->get_base($return[0]));
362 $this->data['thumbnail'] = $thumbnail;
363 }
364 } else {
365 $this->data['thumbnail'] = null;
366 }
367 }
368 return $this->data['thumbnail'];
369 }
370
371 /**
372 * Get a category for the item
373 *
374 * @since Beta 3 (previously called `get_categories()` since Beta 2)
375 * @param int $key The category that you want to return. Remember that arrays begin with 0, not 1
376 * @return \SimplePie\Category|null
377 */
378 public function get_category(int $key = 0)
379 {
380 $categories = $this->get_categories();
381 if (isset($categories[$key])) {
382 return $categories[$key];
383 }
384
385 return null;
386 }
387
388 /**
389 * Get all categories for the item
390 *
391 * Uses `<atom:category>`, `<category>` or `<dc:subject>`
392 *
393 * @since Beta 3
394 * @return \SimplePie\Category[]|null List of {@see \SimplePie\Category} objects
395 */
396 public function get_categories()
397 {
398 $categories = [];
399
400 $type = 'category';
401 foreach ((array) $this->get_item_tags(\SimplePie\SimplePie::NAMESPACE_ATOM_10, $type) as $category) {
402 $term = null;
403 $scheme = null;
404 $label = null;
405 if (isset($category['attribs']['']['term'])) {
406 $term = $this->sanitize($category['attribs']['']['term'], \SimplePie\SimplePie::CONSTRUCT_TEXT);
407 }
408 if (isset($category['attribs']['']['scheme'])) {
409 $scheme = $this->sanitize($category['attribs']['']['scheme'], \SimplePie\SimplePie::CONSTRUCT_TEXT);
410 }
411 if (isset($category['attribs']['']['label'])) {
412 $label = $this->sanitize($category['attribs']['']['label'], \SimplePie\SimplePie::CONSTRUCT_TEXT);
413 }
414 $categories[] = $this->registry->create(Category::class, [$term, $scheme, $label, $type]);
415 }
416 foreach ((array) $this->get_item_tags(\SimplePie\SimplePie::NAMESPACE_RSS_20, $type) as $category) {
417 // This is really the label, but keep this as the term also for BC.
418 // Label will also work on retrieving because that falls back to term.
419 $term = $this->sanitize($category['data'], \SimplePie\SimplePie::CONSTRUCT_TEXT);
420 if (isset($category['attribs']['']['domain'])) {
421 $scheme = $this->sanitize($category['attribs']['']['domain'], \SimplePie\SimplePie::CONSTRUCT_TEXT);
422 } else {
423 $scheme = null;
424 }
425 $categories[] = $this->registry->create(Category::class, [$term, $scheme, null, $type]);
426 }
427
428 $type = 'subject';
429 foreach ((array) $this->get_item_tags(\SimplePie\SimplePie::NAMESPACE_DC_11, $type) as $category) {
430 $categories[] = $this->registry->create(Category::class, [$this->sanitize($category['data'], \SimplePie\SimplePie::CONSTRUCT_TEXT), null, null, $type]);
431 }
432 foreach ((array) $this->get_item_tags(\SimplePie\SimplePie::NAMESPACE_DC_10, $type) as $category) {
433 $categories[] = $this->registry->create(Category::class, [$this->sanitize($category['data'], \SimplePie\SimplePie::CONSTRUCT_TEXT), null, null, $type]);
434 }
435
436 if (!empty($categories)) {
437 return array_unique($categories);
438 }
439
440 return null;
441 }
442
443 /**
444 * Get an author for the item
445 *
446 * @since Beta 2
447 * @param int $key The author that you want to return. Remember that arrays begin with 0, not 1
448 * @return \SimplePie\Author|null
449 */
450 public function get_author(int $key = 0)
451 {
452 $authors = $this->get_authors();
453 if (isset($authors[$key])) {
454 return $authors[$key];
455 }
456
457 return null;
458 }
459
460 /**
461 * Get a contributor for the item
462 *
463 * @since 1.1
464 * @param int $key The contrbutor that you want to return. Remember that arrays begin with 0, not 1
465 * @return \SimplePie\Author|null
466 */
467 public function get_contributor(int $key = 0)
468 {
469 $contributors = $this->get_contributors();
470 if (isset($contributors[$key])) {
471 return $contributors[$key];
472 }
473
474 return null;
475 }
476
477 /**
478 * Get all contributors for the item
479 *
480 * Uses `<atom:contributor>`
481 *
482 * @since 1.1
483 * @return \SimplePie\Author[]|null List of {@see \SimplePie\Author} objects
484 */
485 public function get_contributors()
486 {
487 $contributors = [];
488 foreach ((array) $this->get_item_tags(\SimplePie\SimplePie::NAMESPACE_ATOM_10, 'contributor') as $contributor) {
489 $name = null;
490 $uri = null;
491 $email = null;
492 if (isset($contributor['child'][\SimplePie\SimplePie::NAMESPACE_ATOM_10]['name'][0]['data'])) {
493 $name = $this->sanitize($contributor['child'][\SimplePie\SimplePie::NAMESPACE_ATOM_10]['name'][0]['data'], \SimplePie\SimplePie::CONSTRUCT_TEXT);
494 }
495 if (isset($contributor['child'][\SimplePie\SimplePie::NAMESPACE_ATOM_10]['uri'][0]['data'])) {
496 $uri = $contributor['child'][\SimplePie\SimplePie::NAMESPACE_ATOM_10]['uri'][0];
497 $uri = $this->sanitize($uri['data'], \SimplePie\SimplePie::CONSTRUCT_IRI, $this->get_base($uri));
498 }
499 if (isset($contributor['child'][\SimplePie\SimplePie::NAMESPACE_ATOM_10]['email'][0]['data'])) {
500 $email = $this->sanitize($contributor['child'][\SimplePie\SimplePie::NAMESPACE_ATOM_10]['email'][0]['data'], \SimplePie\SimplePie::CONSTRUCT_TEXT);
501 }
502 if ($name !== null || $email !== null || $uri !== null) {
503 $contributors[] = $this->registry->create(Author::class, [$name, $uri, $email]);
504 }
505 }
506 foreach ((array) $this->get_item_tags(\SimplePie\SimplePie::NAMESPACE_ATOM_03, 'contributor') as $contributor) {
507 $name = null;
508 $url = null;
509 $email = null;
510 if (isset($contributor['child'][\SimplePie\SimplePie::NAMESPACE_ATOM_03]['name'][0]['data'])) {
511 $name = $this->sanitize($contributor['child'][\SimplePie\SimplePie::NAMESPACE_ATOM_03]['name'][0]['data'], \SimplePie\SimplePie::CONSTRUCT_TEXT);
512 }
513 if (isset($contributor['child'][\SimplePie\SimplePie::NAMESPACE_ATOM_03]['url'][0]['data'])) {
514 $url = $contributor['child'][\SimplePie\SimplePie::NAMESPACE_ATOM_03]['url'][0];
515 $url = $this->sanitize($url['data'], \SimplePie\SimplePie::CONSTRUCT_IRI, $this->get_base($url));
516 }
517 if (isset($contributor['child'][\SimplePie\SimplePie::NAMESPACE_ATOM_03]['email'][0]['data'])) {
518 $email = $this->sanitize($contributor['child'][\SimplePie\SimplePie::NAMESPACE_ATOM_03]['email'][0]['data'], \SimplePie\SimplePie::CONSTRUCT_TEXT);
519 }
520 if ($name !== null || $email !== null || $url !== null) {
521 $contributors[] = $this->registry->create(Author::class, [$name, $url, $email]);
522 }
523 }
524
525 if (!empty($contributors)) {
526 return array_unique($contributors);
527 }
528
529 return null;
530 }
531
532 /**
533 * Get all authors for the item
534 *
535 * Uses `<atom:author>`, `<author>`, `<dc:creator>` or `<itunes:author>`
536 *
537 * @since Beta 2
538 * @return \SimplePie\Author[]|null List of {@see \SimplePie\Author} objects
539 */
540 public function get_authors()
541 {
542 $authors = [];
543 foreach ((array) $this->get_item_tags(\SimplePie\SimplePie::NAMESPACE_ATOM_10, 'author') as $author) {
544 $name = null;
545 $uri = null;
546 $email = null;
547 if (isset($author['child'][\SimplePie\SimplePie::NAMESPACE_ATOM_10]['name'][0]['data'])) {
548 $name = $this->sanitize($author['child'][\SimplePie\SimplePie::NAMESPACE_ATOM_10]['name'][0]['data'], \SimplePie\SimplePie::CONSTRUCT_TEXT);
549 }
550 if (isset($author['child'][\SimplePie\SimplePie::NAMESPACE_ATOM_10]['uri'][0]['data'])) {
551 $uri = $author['child'][\SimplePie\SimplePie::NAMESPACE_ATOM_10]['uri'][0];
552 $uri = $this->sanitize($uri['data'], \SimplePie\SimplePie::CONSTRUCT_IRI, $this->get_base($uri));
553 }
554 if (isset($author['child'][\SimplePie\SimplePie::NAMESPACE_ATOM_10]['email'][0]['data'])) {
555 $email = $this->sanitize($author['child'][\SimplePie\SimplePie::NAMESPACE_ATOM_10]['email'][0]['data'], \SimplePie\SimplePie::CONSTRUCT_TEXT);
556 }
557 if ($name !== null || $email !== null || $uri !== null) {
558 $authors[] = $this->registry->create(Author::class, [$name, $uri, $email]);
559 }
560 }
561 if ($author = $this->get_item_tags(\SimplePie\SimplePie::NAMESPACE_ATOM_03, 'author')) {
562 $name = null;
563 $url = null;
564 $email = null;
565 if (isset($author[0]['child'][\SimplePie\SimplePie::NAMESPACE_ATOM_03]['name'][0]['data'])) {
566 $name = $this->sanitize($author[0]['child'][\SimplePie\SimplePie::NAMESPACE_ATOM_03]['name'][0]['data'], \SimplePie\SimplePie::CONSTRUCT_TEXT);
567 }
568 if (isset($author[0]['child'][\SimplePie\SimplePie::NAMESPACE_ATOM_03]['url'][0]['data'])) {
569 $url = $author[0]['child'][\SimplePie\SimplePie::NAMESPACE_ATOM_03]['url'][0];
570 $url = $this->sanitize($url['data'], \SimplePie\SimplePie::CONSTRUCT_IRI, $this->get_base($url));
571 }
572 if (isset($author[0]['child'][\SimplePie\SimplePie::NAMESPACE_ATOM_03]['email'][0]['data'])) {
573 $email = $this->sanitize($author[0]['child'][\SimplePie\SimplePie::NAMESPACE_ATOM_03]['email'][0]['data'], \SimplePie\SimplePie::CONSTRUCT_TEXT);
574 }
575 if ($name !== null || $email !== null || $url !== null) {
576 $authors[] = $this->registry->create(Author::class, [$name, $url, $email]);
577 }
578 }
579 if ($author = $this->get_item_tags(\SimplePie\SimplePie::NAMESPACE_RSS_20, 'author')) {
580 $authors[] = $this->registry->create(Author::class, [null, null, $this->sanitize($author[0]['data'], \SimplePie\SimplePie::CONSTRUCT_TEXT)]);
581 }
582 foreach ((array) $this->get_item_tags(\SimplePie\SimplePie::NAMESPACE_DC_11, 'creator') as $author) {
583 $authors[] = $this->registry->create(Author::class, [$this->sanitize($author['data'], \SimplePie\SimplePie::CONSTRUCT_TEXT), null, null]);
584 }
585 foreach ((array) $this->get_item_tags(\SimplePie\SimplePie::NAMESPACE_DC_10, 'creator') as $author) {
586 $authors[] = $this->registry->create(Author::class, [$this->sanitize($author['data'], \SimplePie\SimplePie::CONSTRUCT_TEXT), null, null]);
587 }
588 foreach ((array) $this->get_item_tags(\SimplePie\SimplePie::NAMESPACE_ITUNES, 'author') as $author) {
589 $authors[] = $this->registry->create(Author::class, [$this->sanitize($author['data'], \SimplePie\SimplePie::CONSTRUCT_TEXT), null, null]);
590 }
591
592 if (!empty($authors)) {
593 return array_unique($authors);
594 } elseif (($source = $this->get_source()) && ($authors = $source->get_authors())) {
595 return $authors;
596 } elseif ($authors = $this->feed->get_authors()) {
597 return $authors;
598 }
599
600 return null;
601 }
602
603 /**
604 * Get the copyright info for the item
605 *
606 * Uses `<atom:rights>` or `<dc:rights>`
607 *
608 * @since 1.1
609 * @return string|null
610 */
611 public function get_copyright()
612 {
613 if ($return = $this->get_item_tags(\SimplePie\SimplePie::NAMESPACE_ATOM_10, 'rights')) {
614 return $this->sanitize($return[0]['data'], $this->registry->call(Misc::class, 'atom_10_construct_type', [$return[0]['attribs']]), $this->get_base($return[0]));
615 } elseif ($return = $this->get_item_tags(\SimplePie\SimplePie::NAMESPACE_DC_11, 'rights')) {
616 return $this->sanitize($return[0]['data'], \SimplePie\SimplePie::CONSTRUCT_TEXT);
617 } elseif ($return = $this->get_item_tags(\SimplePie\SimplePie::NAMESPACE_DC_10, 'rights')) {
618 return $this->sanitize($return[0]['data'], \SimplePie\SimplePie::CONSTRUCT_TEXT);
619 }
620
621 return null;
622 }
623
624 /**
625 * Get the posting date/time for the item
626 *
627 * Uses `<atom:published>`, `<atom:updated>`, `<atom:issued>`,
628 * `<atom:modified>`, `<pubDate>` or `<dc:date>`
629 *
630 * Note: obeys PHP's timezone setting. To get a UTC date/time, use
631 * {@see get_gmdate}
632 *
633 * @since Beta 2 (previously called `get_item_date` since 0.8)
634 *
635 * @param string $date_format Supports any PHP date format from {@see http://php.net/date} (empty for the raw data)
636 * @return ($date_format is 'U' ? ?int : ?string)
637 */
638 public function get_date(string $date_format = 'j F Y, g:i a')
639 {
640 if (!isset($this->data['date'])) {
641 if ($return = $this->get_item_tags(\SimplePie\SimplePie::NAMESPACE_ATOM_10, 'published')) {
642 $this->data['date']['raw'] = $return[0]['data'];
643 } elseif ($return = $this->get_item_tags(\SimplePie\SimplePie::NAMESPACE_RSS_20, 'pubDate')) {
644 $this->data['date']['raw'] = $return[0]['data'];
645 } elseif ($return = $this->get_item_tags(\SimplePie\SimplePie::NAMESPACE_DC_11, 'date')) {
646 $this->data['date']['raw'] = $return[0]['data'];
647 } elseif ($return = $this->get_item_tags(\SimplePie\SimplePie::NAMESPACE_DC_10, 'date')) {
648 $this->data['date']['raw'] = $return[0]['data'];
649 } elseif ($return = $this->get_item_tags(\SimplePie\SimplePie::NAMESPACE_ATOM_10, 'updated')) {
650 $this->data['date']['raw'] = $return[0]['data'];
651 } elseif ($return = $this->get_item_tags(\SimplePie\SimplePie::NAMESPACE_ATOM_03, 'issued')) {
652 $this->data['date']['raw'] = $return[0]['data'];
653 } elseif ($return = $this->get_item_tags(\SimplePie\SimplePie::NAMESPACE_ATOM_03, 'created')) {
654 $this->data['date']['raw'] = $return[0]['data'];
655 } elseif ($return = $this->get_item_tags(\SimplePie\SimplePie::NAMESPACE_ATOM_03, 'modified')) {
656 $this->data['date']['raw'] = $return[0]['data'];
657 }
658
659 if (!empty($this->data['date']['raw'])) {
660 $parser = $this->registry->call(Parse\Date::class, 'get');
661 $this->data['date']['parsed'] = $parser->parse($this->data['date']['raw']) ?: null;
662 } else {
663 $this->data['date'] = null;
664 }
665 }
666 if ($this->data['date']) {
667 switch ($date_format) {
668 case '':
669 return $this->sanitize($this->data['date']['raw'], \SimplePie\SimplePie::CONSTRUCT_TEXT);
670
671 case 'U':
672 return $this->data['date']['parsed'];
673
674 default:
675 return date($date_format, $this->data['date']['parsed']);
676 }
677 }
678
679 return null;
680 }
681
682 /**
683 * Get the update date/time for the item
684 *
685 * Uses `<atom:updated>`
686 *
687 * Note: obeys PHP's timezone setting. To get a UTC date/time, use
688 * {@see get_gmdate}
689 *
690 * @param string $date_format Supports any PHP date format from {@see http://php.net/date} (empty for the raw data)
691 * @return ($date_format is 'U' ? ?int : ?string)
692 */
693 public function get_updated_date(string $date_format = 'j F Y, g:i a')
694 {
695 if (!isset($this->data['updated'])) {
696 if ($return = $this->get_item_tags(\SimplePie\SimplePie::NAMESPACE_ATOM_10, 'updated')) {
697 $this->data['updated']['raw'] = $return[0]['data'];
698 }
699
700 if (!empty($this->data['updated']['raw'])) {
701 $parser = $this->registry->call(Parse\Date::class, 'get');
702 $this->data['updated']['parsed'] = $parser->parse($this->data['updated']['raw']) ?: null;
703 } else {
704 $this->data['updated'] = null;
705 }
706 }
707 if ($this->data['updated']) {
708 switch ($date_format) {
709 case '':
710 return $this->sanitize($this->data['updated']['raw'], \SimplePie\SimplePie::CONSTRUCT_TEXT);
711
712 case 'U':
713 return $this->data['updated']['parsed'];
714
715 default:
716 return date($date_format, $this->data['updated']['parsed']);
717 }
718 }
719
720 return null;
721 }
722
723 /**
724 * Get the localized posting date/time for the item
725 *
726 * Returns the date formatted in the localized language. To display in
727 * languages other than the server's default, you need to change the locale
728 * with {@link http://php.net/setlocale setlocale()}. The available
729 * localizations depend on which ones are installed on your web server.
730 *
731 * @since 1.0
732 *
733 * @param string $date_format Supports any PHP date format from {@see http://php.net/strftime} (empty for the raw data)
734 * @return string|null|false see `strftime` for when this can return `false`
735 */
736 public function get_local_date(string $date_format = '%c')
737 {
738 if ($date_format === '') {
739 if (($raw_date = $this->get_date('')) === null) {
740 return null;
741 }
742
743 return $this->sanitize($raw_date, \SimplePie\SimplePie::CONSTRUCT_TEXT);
744 } elseif (($date = $this->get_date('U')) !== null && $date !== false) {
745 return strftime($date_format, $date);
746 }
747
748 return null;
749 }
750
751 /**
752 * Get the posting date/time for the item (UTC time)
753 *
754 * @see get_date
755 * @param string $date_format Supports any PHP date format from {@see http://php.net/date}
756 * @return string|null
757 */
758 public function get_gmdate(string $date_format = 'j F Y, g:i a')
759 {
760 $date = $this->get_date('U');
761 if ($date === null) {
762 return null;
763 }
764
765 return gmdate($date_format, $date);
766 }
767
768 /**
769 * Get the update date/time for the item (UTC time)
770 *
771 * @see get_updated_date
772 * @param string $date_format Supports any PHP date format from {@see http://php.net/date}
773 * @return string|null
774 */
775 public function get_updated_gmdate(string $date_format = 'j F Y, g:i a')
776 {
777 $date = $this->get_updated_date('U');
778 if ($date === null) {
779 return null;
780 }
781
782 return gmdate($date_format, $date);
783 }
784
785 /**
786 * Get the permalink for the item
787 *
788 * Returns the first link available with a relationship of "alternate".
789 * Identical to {@see get_link()} with key 0
790 *
791 * @see get_link
792 * @since 0.8
793 * @return string|null Permalink URL
794 */
795 public function get_permalink()
796 {
797 $link = $this->get_link();
798 $enclosure = $this->get_enclosure(0);
799 if ($link !== null) {
800 return $link;
801 } elseif ($enclosure !== null) {
802 return $enclosure->get_link();
803 }
804
805 return null;
806 }
807
808 /**
809 * Get a single link for the item
810 *
811 * @since Beta 3
812 * @param int $key The link that you want to return. Remember that arrays begin with 0, not 1
813 * @param string $rel The relationship of the link to return
814 * @return string|null Link URL
815 */
816 public function get_link(int $key = 0, string $rel = 'alternate')
817 {
818 $links = $this->get_links($rel);
819 if ($links && $links[$key] !== null) {
820 return $links[$key];
821 }
822
823 return null;
824 }
825
826 /**
827 * Get all links for the item
828 *
829 * Uses `<atom:link>`, `<link>` or `<guid>`
830 *
831 * @since Beta 2
832 * @param string $rel The relationship of links to return
833 * @return array<string>|null Links found for the item (strings)
834 */
835 public function get_links(string $rel = 'alternate')
836 {
837 if (!isset($this->data['links'])) {
838 $this->data['links'] = [];
839 foreach ((array) $this->get_item_tags(\SimplePie\SimplePie::NAMESPACE_ATOM_10, 'link') as $link) {
840 if (isset($link['attribs']['']['href'])) {
841 $link_rel = (isset($link['attribs']['']['rel'])) ? $link['attribs']['']['rel'] : 'alternate';
842 $this->data['links'][$link_rel][] = $this->sanitize($link['attribs']['']['href'], \SimplePie\SimplePie::CONSTRUCT_IRI, $this->get_own_base($link));
843 }
844 }
845 foreach ((array) $this->get_item_tags(\SimplePie\SimplePie::NAMESPACE_ATOM_03, 'link') as $link) {
846 if (isset($link['attribs']['']['href'])) {
847 $link_rel = (isset($link['attribs']['']['rel'])) ? $link['attribs']['']['rel'] : 'alternate';
848 $this->data['links'][$link_rel][] = $this->sanitize($link['attribs']['']['href'], \SimplePie\SimplePie::CONSTRUCT_IRI, $this->get_own_base($link));
849 }
850 }
851 if ($links = $this->get_item_tags(\SimplePie\SimplePie::NAMESPACE_RSS_10, 'link')) {
852 $this->data['links']['alternate'][] = $this->sanitize($links[0]['data'], \SimplePie\SimplePie::CONSTRUCT_IRI, $this->get_own_base($links[0]));
853 }
854 if ($links = $this->get_item_tags(\SimplePie\SimplePie::NAMESPACE_RSS_090, 'link')) {
855 $this->data['links']['alternate'][] = $this->sanitize($links[0]['data'], \SimplePie\SimplePie::CONSTRUCT_IRI, $this->get_own_base($links[0]));
856 }
857 if ($links = $this->get_item_tags(\SimplePie\SimplePie::NAMESPACE_RSS_20, 'link')) {
858 $this->data['links']['alternate'][] = $this->sanitize($links[0]['data'], \SimplePie\SimplePie::CONSTRUCT_IRI, $this->get_own_base($links[0]));
859 }
860 if ($links = $this->get_item_tags(\SimplePie\SimplePie::NAMESPACE_RSS_20, 'guid')) {
861 if (!isset($links[0]['attribs']['']['isPermaLink']) || strtolower(trim($links[0]['attribs']['']['isPermaLink'])) === 'true') {
862 $this->data['links']['alternate'][] = $this->sanitize($links[0]['data'], \SimplePie\SimplePie::CONSTRUCT_IRI, $this->get_own_base($links[0]));
863 }
864 }
865
866 $keys = array_keys($this->data['links']);
867 foreach ($keys as $key) {
868 if ($this->registry->call(Misc::class, 'is_isegment_nz_nc', [$key])) {
869 if (isset($this->data['links'][\SimplePie\SimplePie::IANA_LINK_RELATIONS_REGISTRY . $key])) {
870 $this->data['links'][\SimplePie\SimplePie::IANA_LINK_RELATIONS_REGISTRY . $key] = array_merge($this->data['links'][$key], $this->data['links'][\SimplePie\SimplePie::IANA_LINK_RELATIONS_REGISTRY . $key]);
871 $this->data['links'][$key] = &$this->data['links'][\SimplePie\SimplePie::IANA_LINK_RELATIONS_REGISTRY . $key];
872 } else {
873 $this->data['links'][\SimplePie\SimplePie::IANA_LINK_RELATIONS_REGISTRY . $key] = &$this->data['links'][$key];
874 }
875 } elseif (substr((string) $key, 0, 41) === \SimplePie\SimplePie::IANA_LINK_RELATIONS_REGISTRY) {
876 $this->data['links'][substr((string) $key, 41)] = &$this->data['links'][$key];
877 }
878 $this->data['links'][$key] = array_unique($this->data['links'][$key]);
879 }
880 }
881 if (isset($this->data['links'][$rel])) {
882 return $this->data['links'][$rel];
883 }
884
885 return null;
886 }
887
888 /**
889 * Get an enclosure from the item
890 *
891 * Supports the <enclosure> RSS tag, as well as Media RSS and iTunes RSS.
892 *
893 * @since Beta 2
894 * @todo Add ability to prefer one type of content over another (in a media group).
895 * @param int $key The enclosure that you want to return. Remember that arrays begin with 0, not 1
896 * @return \SimplePie\Enclosure|null
897 */
898 public function get_enclosure(int $key = 0)
899 {
900 $enclosures = $this->get_enclosures();
901 if (isset($enclosures[$key])) {
902 return $enclosures[$key];
903 }
904
905 return null;
906 }
907
908 /**
909 * Get all available enclosures (podcasts, etc.)
910 *
911 * Supports the <enclosure> RSS tag, as well as Media RSS and iTunes RSS.
912 *
913 * At this point, we're pretty much assuming that all enclosures for an item
914 * are the same content. Anything else is too complicated to
915 * properly support.
916 *
917 * @since Beta 2
918 * @todo Add support for end-user defined sorting of enclosures by type/handler (so we can prefer the faster-loading FLV over MP4).
919 * @todo If an element exists at a level, but its value is empty, we should fall back to the value from the parent (if it exists).
920 * @return \SimplePie\Enclosure[]|null List of \SimplePie\Enclosure items
921 */
922 public function get_enclosures()
923 {
924 if (!isset($this->data['enclosures'])) {
925 $this->data['enclosures'] = [];
926
927 // Elements
928 $captions_parent = null;
929 $categories_parent = null;
930 $copyrights_parent = null;
931 $credits_parent = null;
932 $description_parent = null;
933 $duration_parent = null;
934 $hashes_parent = null;
935 $keywords_parent = null;
936 $player_parent = null;
937 $ratings_parent = null;
938 $restrictions_parent = [];
939 $thumbnails_parent = null;
940 $title_parent = null;
941
942 // Let's do the channel and item-level ones first, and just re-use them if we need to.
943 $parent = $this->get_feed();
944
945 // CAPTIONS
946 if ($captions = $this->get_item_tags(\SimplePie\SimplePie::NAMESPACE_MEDIARSS, 'text')) {
947 foreach ($captions as $caption) {
948 $caption_type = null;
949 $caption_lang = null;
950 $caption_startTime = null;
951 $caption_endTime = null;
952 $caption_text = null;
953 if (isset($caption['attribs']['']['type'])) {
954 $caption_type = $this->sanitize($caption['attribs']['']['type'], \SimplePie\SimplePie::CONSTRUCT_TEXT);
955 }
956 if (isset($caption['attribs']['']['lang'])) {
957 $caption_lang = $this->sanitize($caption['attribs']['']['lang'], \SimplePie\SimplePie::CONSTRUCT_TEXT);
958 }
959 if (isset($caption['attribs']['']['start'])) {
960 $caption_startTime = $this->sanitize($caption['attribs']['']['start'], \SimplePie\SimplePie::CONSTRUCT_TEXT);
961 }
962 if (isset($caption['attribs']['']['end'])) {
963 $caption_endTime = $this->sanitize($caption['attribs']['']['end'], \SimplePie\SimplePie::CONSTRUCT_TEXT);
964 }
965 if (isset($caption['data'])) {
966 $caption_text = $this->sanitize($caption['data'], \SimplePie\SimplePie::CONSTRUCT_TEXT);
967 }
968 $captions_parent[] = $this->registry->create(Caption::class, [$caption_type, $caption_lang, $caption_startTime, $caption_endTime, $caption_text]);
969 }
970 } elseif ($captions = $parent->get_channel_tags(\SimplePie\SimplePie::NAMESPACE_MEDIARSS, 'text')) {
971 foreach ($captions as $caption) {
972 $caption_type = null;
973 $caption_lang = null;
974 $caption_startTime = null;
975 $caption_endTime = null;
976 $caption_text = null;
977 if (isset($caption['attribs']['']['type'])) {
978 $caption_type = $this->sanitize($caption['attribs']['']['type'], \SimplePie\SimplePie::CONSTRUCT_TEXT);
979 }
980 if (isset($caption['attribs']['']['lang'])) {
981 $caption_lang = $this->sanitize($caption['attribs']['']['lang'], \SimplePie\SimplePie::CONSTRUCT_TEXT);
982 }
983 if (isset($caption['attribs']['']['start'])) {
984 $caption_startTime = $this->sanitize($caption['attribs']['']['start'], \SimplePie\SimplePie::CONSTRUCT_TEXT);
985 }
986 if (isset($caption['attribs']['']['end'])) {
987 $caption_endTime = $this->sanitize($caption['attribs']['']['end'], \SimplePie\SimplePie::CONSTRUCT_TEXT);
988 }
989 if (isset($caption['data'])) {
990 $caption_text = $this->sanitize($caption['data'], \SimplePie\SimplePie::CONSTRUCT_TEXT);
991 }
992 $captions_parent[] = $this->registry->create(Caption::class, [$caption_type, $caption_lang, $caption_startTime, $caption_endTime, $caption_text]);
993 }
994 }
995 if (is_array($captions_parent)) {
996 $captions_parent = array_values(array_unique($captions_parent));
997 }
998
999 // CATEGORIES
1000 foreach ((array) $this->get_item_tags(\SimplePie\SimplePie::NAMESPACE_MEDIARSS, 'category') as $category) {
1001 $term = null;
1002 $scheme = null;
1003 $label = null;
1004 if (isset($category['data'])) {
1005 $term = $this->sanitize($category['data'], \SimplePie\SimplePie::CONSTRUCT_TEXT);
1006 }
1007 if (isset($category['attribs']['']['scheme'])) {
1008 $scheme = $this->sanitize($category['attribs']['']['scheme'], \SimplePie\SimplePie::CONSTRUCT_TEXT);
1009 } else {
1010 $scheme = 'http://search.yahoo.com/mrss/category_schema';
1011 }
1012 if (isset($category['attribs']['']['label'])) {
1013 $label = $this->sanitize($category['attribs']['']['label'], \SimplePie\SimplePie::CONSTRUCT_TEXT);
1014 }
1015 $categories_parent[] = $this->registry->create(Category::class, [$term, $scheme, $label]);
1016 }
1017 foreach ((array) $parent->get_channel_tags(\SimplePie\SimplePie::NAMESPACE_MEDIARSS, 'category') as $category) {
1018 $term = null;
1019 $scheme = null;
1020 $label = null;
1021 if (isset($category['data'])) {
1022 $term = $this->sanitize($category['data'], \SimplePie\SimplePie::CONSTRUCT_TEXT);
1023 }
1024 if (isset($category['attribs']['']['scheme'])) {
1025 $scheme = $this->sanitize($category['attribs']['']['scheme'], \SimplePie\SimplePie::CONSTRUCT_TEXT);
1026 } else {
1027 $scheme = 'http://search.yahoo.com/mrss/category_schema';
1028 }
1029 if (isset($category['attribs']['']['label'])) {
1030 $label = $this->sanitize($category['attribs']['']['label'], \SimplePie\SimplePie::CONSTRUCT_TEXT);
1031 }
1032 $categories_parent[] = $this->registry->create(Category::class, [$term, $scheme, $label]);
1033 }
1034 foreach ((array) $parent->get_channel_tags(\SimplePie\SimplePie::NAMESPACE_ITUNES, 'category') as $category) {
1035 $term = null;
1036 $scheme = 'http://www.itunes.com/dtds/podcast-1.0.dtd';
1037 $label = null;
1038 if (isset($category['attribs']['']['text'])) {
1039 $label = $this->sanitize($category['attribs']['']['text'], \SimplePie\SimplePie::CONSTRUCT_TEXT);
1040 }
1041 $categories_parent[] = $this->registry->create(Category::class, [$term, $scheme, $label]);
1042
1043 if (isset($category['child'][\SimplePie\SimplePie::NAMESPACE_ITUNES]['category'])) {
1044 foreach ((array) $category['child'][\SimplePie\SimplePie::NAMESPACE_ITUNES]['category'] as $subcategory) {
1045 if (isset($subcategory['attribs']['']['text'])) {
1046 $label = $this->sanitize($subcategory['attribs']['']['text'], \SimplePie\SimplePie::CONSTRUCT_TEXT);
1047 }
1048 $categories_parent[] = $this->registry->create(Category::class, [$term, $scheme, $label]);
1049 }
1050 }
1051 }
1052 if (is_array($categories_parent)) {
1053 $categories_parent = array_values(array_unique($categories_parent));
1054 }
1055
1056 // COPYRIGHT
1057 if ($copyright = $this->get_item_tags(\SimplePie\SimplePie::NAMESPACE_MEDIARSS, 'copyright')) {
1058 $copyright_url = null;
1059 $copyright_label = null;
1060 if (isset($copyright[0]['attribs']['']['url'])) {
1061 $copyright_url = $this->sanitize($copyright[0]['attribs']['']['url'], \SimplePie\SimplePie::CONSTRUCT_TEXT);
1062 }
1063 if (isset($copyright[0]['data'])) {
1064 $copyright_label = $this->sanitize($copyright[0]['data'], \SimplePie\SimplePie::CONSTRUCT_TEXT);
1065 }
1066 $copyrights_parent = $this->registry->create(Copyright::class, [$copyright_url, $copyright_label]);
1067 } elseif ($copyright = $parent->get_channel_tags(\SimplePie\SimplePie::NAMESPACE_MEDIARSS, 'copyright')) {
1068 $copyright_url = null;
1069 $copyright_label = null;
1070 if (isset($copyright[0]['attribs']['']['url'])) {
1071 $copyright_url = $this->sanitize($copyright[0]['attribs']['']['url'], \SimplePie\SimplePie::CONSTRUCT_TEXT);
1072 }
1073 if (isset($copyright[0]['data'])) {
1074 $copyright_label = $this->sanitize($copyright[0]['data'], \SimplePie\SimplePie::CONSTRUCT_TEXT);
1075 }
1076 $copyrights_parent = $this->registry->create(Copyright::class, [$copyright_url, $copyright_label]);
1077 }
1078
1079 // CREDITS
1080 if ($credits = $this->get_item_tags(\SimplePie\SimplePie::NAMESPACE_MEDIARSS, 'credit')) {
1081 foreach ($credits as $credit) {
1082 $credit_role = null;
1083 $credit_scheme = null;
1084 $credit_name = null;
1085 if (isset($credit['attribs']['']['role'])) {
1086 $credit_role = $this->sanitize($credit['attribs']['']['role'], \SimplePie\SimplePie::CONSTRUCT_TEXT);
1087 }
1088 if (isset($credit['attribs']['']['scheme'])) {
1089 $credit_scheme = $this->sanitize($credit['attribs']['']['scheme'], \SimplePie\SimplePie::CONSTRUCT_TEXT);
1090 } else {
1091 $credit_scheme = 'urn:ebu';
1092 }
1093 if (isset($credit['data'])) {
1094 $credit_name = $this->sanitize($credit['data'], \SimplePie\SimplePie::CONSTRUCT_TEXT);
1095 }
1096 $credits_parent[] = $this->registry->create(Credit::class, [$credit_role, $credit_scheme, $credit_name]);
1097 }
1098 } elseif ($credits = $parent->get_channel_tags(\SimplePie\SimplePie::NAMESPACE_MEDIARSS, 'credit')) {
1099 foreach ($credits as $credit) {
1100 $credit_role = null;
1101 $credit_scheme = null;
1102 $credit_name = null;
1103 if (isset($credit['attribs']['']['role'])) {
1104 $credit_role = $this->sanitize($credit['attribs']['']['role'], \SimplePie\SimplePie::CONSTRUCT_TEXT);
1105 }
1106 if (isset($credit['attribs']['']['scheme'])) {
1107 $credit_scheme = $this->sanitize($credit['attribs']['']['scheme'], \SimplePie\SimplePie::CONSTRUCT_TEXT);
1108 } else {
1109 $credit_scheme = 'urn:ebu';
1110 }
1111 if (isset($credit['data'])) {
1112 $credit_name = $this->sanitize($credit['data'], \SimplePie\SimplePie::CONSTRUCT_TEXT);
1113 }
1114 $credits_parent[] = $this->registry->create(Credit::class, [$credit_role, $credit_scheme, $credit_name]);
1115 }
1116 }
1117 if (is_array($credits_parent)) {
1118 $credits_parent = array_values(array_unique($credits_parent));
1119 }
1120
1121 // DESCRIPTION
1122 if ($description_parent = $this->get_item_tags(\SimplePie\SimplePie::NAMESPACE_MEDIARSS, 'description')) {
1123 if (isset($description_parent[0]['data'])) {
1124 $description_parent = $this->sanitize($description_parent[0]['data'], \SimplePie\SimplePie::CONSTRUCT_TEXT);
1125 }
1126 } elseif ($description_parent = $parent->get_channel_tags(\SimplePie\SimplePie::NAMESPACE_MEDIARSS, 'description')) {
1127 if (isset($description_parent[0]['data'])) {
1128 $description_parent = $this->sanitize($description_parent[0]['data'], \SimplePie\SimplePie::CONSTRUCT_TEXT);
1129 }
1130 }
1131
1132 // DURATION
1133 $duration_tags = $this->get_item_tags(\SimplePie\SimplePie::NAMESPACE_ITUNES, 'duration');
1134 if ($duration_tags !== null) {
1135 $seconds = null;
1136 $minutes = null;
1137 $hours = null;
1138 if (isset($duration_tags[0]['data'])) {
1139 $temp = explode(':', $this->sanitize($duration_tags[0]['data'], \SimplePie\SimplePie::CONSTRUCT_TEXT));
1140 $seconds = (int) array_pop($temp);
1141 if (count($temp) > 0) {
1142 $minutes = (int) array_pop($temp);
1143 $seconds += $minutes * 60;
1144 }
1145 if (count($temp) > 0) {
1146 $hours = (int) array_pop($temp);
1147 $seconds += $hours * 3600;
1148 }
1149 unset($temp);
1150 $duration_parent = $seconds;
1151 }
1152 }
1153
1154 // HASHES
1155 if ($hashes_iterator = $this->get_item_tags(\SimplePie\SimplePie::NAMESPACE_MEDIARSS, 'hash')) {
1156 foreach ($hashes_iterator as $hash) {
1157 $value = null;
1158 $algo = null;
1159 if (isset($hash['data'])) {
1160 $value = $this->sanitize($hash['data'], \SimplePie\SimplePie::CONSTRUCT_TEXT);
1161 }
1162 if (isset($hash['attribs']['']['algo'])) {
1163 $algo = $this->sanitize($hash['attribs']['']['algo'], \SimplePie\SimplePie::CONSTRUCT_TEXT);
1164 } else {
1165 $algo = 'md5';
1166 }
1167 $hashes_parent[] = $algo.':'.$value;
1168 }
1169 } elseif ($hashes_iterator = $parent->get_channel_tags(\SimplePie\SimplePie::NAMESPACE_MEDIARSS, 'hash')) {
1170 foreach ($hashes_iterator as $hash) {
1171 $value = null;
1172 $algo = null;
1173 if (isset($hash['data'])) {
1174 $value = $this->sanitize($hash['data'], \SimplePie\SimplePie::CONSTRUCT_TEXT);
1175 }
1176 if (isset($hash['attribs']['']['algo'])) {
1177 $algo = $this->sanitize($hash['attribs']['']['algo'], \SimplePie\SimplePie::CONSTRUCT_TEXT);
1178 } else {
1179 $algo = 'md5';
1180 }
1181 $hashes_parent[] = $algo.':'.$value;
1182 }
1183 }
1184 if (is_array($hashes_parent)) {
1185 $hashes_parent = array_values(array_unique($hashes_parent));
1186 }
1187
1188 // KEYWORDS
1189 if ($keywords = $this->get_item_tags(\SimplePie\SimplePie::NAMESPACE_MEDIARSS, 'keywords')) {
1190 if (isset($keywords[0]['data'])) {
1191 $temp = explode(',', $this->sanitize($keywords[0]['data'], \SimplePie\SimplePie::CONSTRUCT_TEXT));
1192 foreach ($temp as $word) {
1193 $keywords_parent[] = trim($word);
1194 }
1195 }
1196 unset($temp);
1197 } elseif ($keywords = $this->get_item_tags(\SimplePie\SimplePie::NAMESPACE_ITUNES, 'keywords')) {
1198 if (isset($keywords[0]['data'])) {
1199 $temp = explode(',', $this->sanitize($keywords[0]['data'], \SimplePie\SimplePie::CONSTRUCT_TEXT));
1200 foreach ($temp as $word) {
1201 $keywords_parent[] = trim($word);
1202 }
1203 }
1204 unset($temp);
1205 } elseif ($keywords = $parent->get_channel_tags(\SimplePie\SimplePie::NAMESPACE_MEDIARSS, 'keywords')) {
1206 if (isset($keywords[0]['data'])) {
1207 $temp = explode(',', $this->sanitize($keywords[0]['data'], \SimplePie\SimplePie::CONSTRUCT_TEXT));
1208 foreach ($temp as $word) {
1209 $keywords_parent[] = trim($word);
1210 }
1211 }
1212 unset($temp);
1213 } elseif ($keywords = $parent->get_channel_tags(\SimplePie\SimplePie::NAMESPACE_ITUNES, 'keywords')) {
1214 if (isset($keywords[0]['data'])) {
1215 $temp = explode(',', $this->sanitize($keywords[0]['data'], \SimplePie\SimplePie::CONSTRUCT_TEXT));
1216 foreach ($temp as $word) {
1217 $keywords_parent[] = trim($word);
1218 }
1219 }
1220 unset($temp);
1221 }
1222 if (is_array($keywords_parent)) {
1223 $keywords_parent = array_values(array_unique($keywords_parent));
1224 }
1225
1226 // PLAYER
1227 if ($player_parent = $this->get_item_tags(\SimplePie\SimplePie::NAMESPACE_MEDIARSS, 'player')) {
1228 if (isset($player_parent[0]['attribs']['']['url'])) {
1229 $player_parent = $this->sanitize($player_parent[0]['attribs']['']['url'], \SimplePie\SimplePie::CONSTRUCT_IRI, $this->get_own_base($player_parent[0]));
1230 }
1231 } elseif ($player_parent = $parent->get_channel_tags(\SimplePie\SimplePie::NAMESPACE_MEDIARSS, 'player')) {
1232 if (isset($player_parent[0]['attribs']['']['url'])) {
1233 $player_parent = $this->sanitize($player_parent[0]['attribs']['']['url'], \SimplePie\SimplePie::CONSTRUCT_IRI, $this->get_own_base($player_parent[0]));
1234 }
1235 }
1236
1237 // RATINGS
1238 if ($ratings = $this->get_item_tags(\SimplePie\SimplePie::NAMESPACE_MEDIARSS, 'rating')) {
1239 foreach ($ratings as $rating) {
1240 $rating_scheme = null;
1241 $rating_value = null;
1242 if (isset($rating['attribs']['']['scheme'])) {
1243 $rating_scheme = $this->sanitize($rating['attribs']['']['scheme'], \SimplePie\SimplePie::CONSTRUCT_TEXT);
1244 } else {
1245 $rating_scheme = 'urn:simple';
1246 }
1247 if (isset($rating['data'])) {
1248 $rating_value = $this->sanitize($rating['data'], \SimplePie\SimplePie::CONSTRUCT_TEXT);
1249 }
1250 $ratings_parent[] = $this->registry->create(Rating::class, [$rating_scheme, $rating_value]);
1251 }
1252 } elseif ($ratings = $this->get_item_tags(\SimplePie\SimplePie::NAMESPACE_ITUNES, 'explicit')) {
1253 foreach ($ratings as $rating) {
1254 $rating_scheme = 'urn:itunes';
1255 $rating_value = null;
1256 if (isset($rating['data'])) {
1257 $rating_value = $this->sanitize($rating['data'], \SimplePie\SimplePie::CONSTRUCT_TEXT);
1258 }
1259 $ratings_parent[] = $this->registry->create(Rating::class, [$rating_scheme, $rating_value]);
1260 }
1261 } elseif ($ratings = $parent->get_channel_tags(\SimplePie\SimplePie::NAMESPACE_MEDIARSS, 'rating')) {
1262 foreach ($ratings as $rating) {
1263 $rating_scheme = null;
1264 $rating_value = null;
1265 if (isset($rating['attribs']['']['scheme'])) {
1266 $rating_scheme = $this->sanitize($rating['attribs']['']['scheme'], \SimplePie\SimplePie::CONSTRUCT_TEXT);
1267 } else {
1268 $rating_scheme = 'urn:simple';
1269 }
1270 if (isset($rating['data'])) {
1271 $rating_value = $this->sanitize($rating['data'], \SimplePie\SimplePie::CONSTRUCT_TEXT);
1272 }
1273 $ratings_parent[] = $this->registry->create(Rating::class, [$rating_scheme, $rating_value]);
1274 }
1275 } elseif ($ratings = $parent->get_channel_tags(\SimplePie\SimplePie::NAMESPACE_ITUNES, 'explicit')) {
1276 foreach ($ratings as $rating) {
1277 $rating_scheme = 'urn:itunes';
1278 $rating_value = null;
1279 if (isset($rating['data'])) {
1280 $rating_value = $this->sanitize($rating['data'], \SimplePie\SimplePie::CONSTRUCT_TEXT);
1281 }
1282 $ratings_parent[] = $this->registry->create(Rating::class, [$rating_scheme, $rating_value]);
1283 }
1284 }
1285 if (is_array($ratings_parent)) {
1286 $ratings_parent = array_values(array_unique($ratings_parent));
1287 }
1288
1289 // RESTRICTIONS
1290 if ($restrictions = $this->get_item_tags(\SimplePie\SimplePie::NAMESPACE_MEDIARSS, 'restriction')) {
1291 foreach ($restrictions as $restriction) {
1292 $restriction_relationship = null;
1293 $restriction_type = null;
1294 $restriction_value = null;
1295 if (isset($restriction['attribs']['']['relationship'])) {
1296 $restriction_relationship = $this->sanitize($restriction['attribs']['']['relationship'], \SimplePie\SimplePie::CONSTRUCT_TEXT);
1297 }
1298 if (isset($restriction['attribs']['']['type'])) {
1299 $restriction_type = $this->sanitize($restriction['attribs']['']['type'], \SimplePie\SimplePie::CONSTRUCT_TEXT);
1300 }
1301 if (isset($restriction['data'])) {
1302 $restriction_value = $this->sanitize($restriction['data'], \SimplePie\SimplePie::CONSTRUCT_TEXT);
1303 }
1304 $restrictions_parent[] = $this->registry->create(Restriction::class, [$restriction_relationship, $restriction_type, $restriction_value]);
1305 }
1306 } elseif ($restrictions = $this->get_item_tags(\SimplePie\SimplePie::NAMESPACE_ITUNES, 'block')) {
1307 foreach ($restrictions as $restriction) {
1308 $restriction_relationship = Restriction::RELATIONSHIP_ALLOW;
1309 $restriction_type = null;
1310 $restriction_value = 'itunes';
1311 if (isset($restriction['data']) && strtolower($restriction['data']) === 'yes') {
1312 $restriction_relationship = Restriction::RELATIONSHIP_DENY;
1313 }
1314 $restrictions_parent[] = $this->registry->create(Restriction::class, [$restriction_relationship, $restriction_type, $restriction_value]);
1315 }
1316 } elseif ($restrictions = $parent->get_channel_tags(\SimplePie\SimplePie::NAMESPACE_MEDIARSS, 'restriction')) {
1317 foreach ($restrictions as $restriction) {
1318 $restriction_relationship = null;
1319 $restriction_type = null;
1320 $restriction_value = null;
1321 if (isset($restriction['attribs']['']['relationship'])) {
1322 $restriction_relationship = $this->sanitize($restriction['attribs']['']['relationship'], \SimplePie\SimplePie::CONSTRUCT_TEXT);
1323 }
1324 if (isset($restriction['attribs']['']['type'])) {
1325 $restriction_type = $this->sanitize($restriction['attribs']['']['type'], \SimplePie\SimplePie::CONSTRUCT_TEXT);
1326 }
1327 if (isset($restriction['data'])) {
1328 $restriction_value = $this->sanitize($restriction['data'], \SimplePie\SimplePie::CONSTRUCT_TEXT);
1329 }
1330 $restrictions_parent[] = $this->registry->create(Restriction::class, [$restriction_relationship, $restriction_type, $restriction_value]);
1331 }
1332 } elseif ($restrictions = $parent->get_channel_tags(\SimplePie\SimplePie::NAMESPACE_ITUNES, 'block')) {
1333 foreach ($restrictions as $restriction) {
1334 $restriction_relationship = Restriction::RELATIONSHIP_ALLOW;
1335 $restriction_type = null;
1336 $restriction_value = 'itunes';
1337 if (isset($restriction['data']) && strtolower($restriction['data']) === 'yes') {
1338 $restriction_relationship = Restriction::RELATIONSHIP_DENY;
1339 }
1340 $restrictions_parent[] = $this->registry->create(Restriction::class, [$restriction_relationship, $restriction_type, $restriction_value]);
1341 }
1342 }
1343 if (count($restrictions_parent) > 0) {
1344 $restrictions_parent = array_values(array_unique($restrictions_parent));
1345 } else {
1346 $restrictions_parent = [new \SimplePie\Restriction(Restriction::RELATIONSHIP_ALLOW, null, 'default')];
1347 }
1348
1349 // THUMBNAILS
1350 if ($thumbnails = $this->get_item_tags(\SimplePie\SimplePie::NAMESPACE_MEDIARSS, 'thumbnail')) {
1351 foreach ($thumbnails as $thumbnail) {
1352 if (isset($thumbnail['attribs']['']['url'])) {
1353 $thumbnails_parent[] = $this->sanitize($thumbnail['attribs']['']['url'], \SimplePie\SimplePie::CONSTRUCT_IRI, $this->get_own_base($thumbnail));
1354 }
1355 }
1356 } elseif ($thumbnails = $parent->get_channel_tags(\SimplePie\SimplePie::NAMESPACE_MEDIARSS, 'thumbnail')) {
1357 foreach ($thumbnails as $thumbnail) {
1358 if (isset($thumbnail['attribs']['']['url'])) {
1359 $thumbnails_parent[] = $this->sanitize($thumbnail['attribs']['']['url'], \SimplePie\SimplePie::CONSTRUCT_IRI, $this->get_own_base($thumbnail));
1360 }
1361 }
1362 }
1363
1364 // TITLES
1365 if ($title_parent = $this->get_item_tags(\SimplePie\SimplePie::NAMESPACE_MEDIARSS, 'title')) {
1366 if (isset($title_parent[0]['data'])) {
1367 $title_parent = $this->sanitize($title_parent[0]['data'], \SimplePie\SimplePie::CONSTRUCT_TEXT);
1368 }
1369 } elseif ($title_parent = $parent->get_channel_tags(\SimplePie\SimplePie::NAMESPACE_MEDIARSS, 'title')) {
1370 if (isset($title_parent[0]['data'])) {
1371 $title_parent = $this->sanitize($title_parent[0]['data'], \SimplePie\SimplePie::CONSTRUCT_TEXT);
1372 }
1373 }
1374
1375 // Clear the memory
1376 unset($parent);
1377
1378 // Attributes
1379 $bitrate = null;
1380 $channels = null;
1381 $duration = null;
1382 $expression = null;
1383 $framerate = null;
1384 $height = null;
1385 $javascript = null;
1386 $lang = null;
1387 $length = null;
1388 $medium = null;
1389 $samplingrate = null;
1390 $type = null;
1391 $url = null;
1392 $width = null;
1393
1394 // Elements
1395 $captions = null;
1396 $categories = null;
1397 $copyrights = null;
1398 $credits = null;
1399 $description = null;
1400 $hashes = null;
1401 $keywords = null;
1402 $player = null;
1403 $ratings = null;
1404 $restrictions = null;
1405 $thumbnails = null;
1406 $title = null;
1407
1408 // If we have media:group tags, loop through them.
1409 foreach ((array) $this->get_item_tags(\SimplePie\SimplePie::NAMESPACE_MEDIARSS, 'group') as $group) {
1410 if (isset($group['child']) && isset($group['child'][\SimplePie\SimplePie::NAMESPACE_MEDIARSS]['content'])) {
1411 // If we have media:content tags, loop through them.
1412 foreach ((array) $group['child'][\SimplePie\SimplePie::NAMESPACE_MEDIARSS]['content'] as $content) {
1413 if (isset($content['attribs']['']['url'])) {
1414 // Attributes
1415 $bitrate = null;
1416 $channels = null;
1417 $duration = null;
1418 $expression = null;
1419 $framerate = null;
1420 $height = null;
1421 $javascript = null;
1422 $lang = null;
1423 $length = null;
1424 $medium = null;
1425 $samplingrate = null;
1426 $type = null;
1427 $url = null;
1428 $width = null;
1429
1430 // Elements
1431 $captions = null;
1432 $categories = null;
1433 $copyrights = null;
1434 $credits = null;
1435 $description = null;
1436 $hashes = null;
1437 $keywords = null;
1438 $player = null;
1439 $ratings = null;
1440 $restrictions = null;
1441 $thumbnails = null;
1442 $title = null;
1443
1444 // Start checking the attributes of media:content
1445 if (isset($content['attribs']['']['bitrate'])) {
1446 $bitrate = $this->sanitize($content['attribs']['']['bitrate'], \SimplePie\SimplePie::CONSTRUCT_TEXT);
1447 }
1448 if (isset($content['attribs']['']['channels'])) {
1449 $channels = $this->sanitize($content['attribs']['']['channels'], \SimplePie\SimplePie::CONSTRUCT_TEXT);
1450 }
1451 if (isset($content['attribs']['']['duration'])) {
1452 $duration = $this->sanitize($content['attribs']['']['duration'], \SimplePie\SimplePie::CONSTRUCT_TEXT);
1453 } else {
1454 $duration = $duration_parent;
1455 }
1456 if (isset($content['attribs']['']['expression'])) {
1457 $expression = $this->sanitize($content['attribs']['']['expression'], \SimplePie\SimplePie::CONSTRUCT_TEXT);
1458 }
1459 if (isset($content['attribs']['']['framerate'])) {
1460 $framerate = $this->sanitize($content['attribs']['']['framerate'], \SimplePie\SimplePie::CONSTRUCT_TEXT);
1461 }
1462 if (isset($content['attribs']['']['height'])) {
1463 $height = $this->sanitize($content['attribs']['']['height'], \SimplePie\SimplePie::CONSTRUCT_TEXT);
1464 }
1465 if (isset($content['attribs']['']['lang'])) {
1466 $lang = $this->sanitize($content['attribs']['']['lang'], \SimplePie\SimplePie::CONSTRUCT_TEXT);
1467 }
1468 if (isset($content['attribs']['']['fileSize'])) {
1469 $length = intval($content['attribs']['']['fileSize']);
1470 }
1471 if (isset($content['attribs']['']['medium'])) {
1472 $medium = $this->sanitize($content['attribs']['']['medium'], \SimplePie\SimplePie::CONSTRUCT_TEXT);
1473 }
1474 if (isset($content['attribs']['']['samplingrate'])) {
1475 $samplingrate = $this->sanitize($content['attribs']['']['samplingrate'], \SimplePie\SimplePie::CONSTRUCT_TEXT);
1476 }
1477 if (isset($content['attribs']['']['type'])) {
1478 $type = $this->sanitize($content['attribs']['']['type'], \SimplePie\SimplePie::CONSTRUCT_TEXT);
1479 }
1480 if (isset($content['attribs']['']['width'])) {
1481 $width = $this->sanitize($content['attribs']['']['width'], \SimplePie\SimplePie::CONSTRUCT_TEXT);
1482 }
1483 $url = $this->sanitize($content['attribs']['']['url'], \SimplePie\SimplePie::CONSTRUCT_IRI, $this->get_own_base($content));
1484
1485 // Checking the other optional media: elements. Priority: media:content, media:group, item, channel
1486
1487 // CAPTIONS
1488 if (isset($content['child'][\SimplePie\SimplePie::NAMESPACE_MEDIARSS]['text'])) {
1489 foreach ($content['child'][\SimplePie\SimplePie::NAMESPACE_MEDIARSS]['text'] as $caption) {
1490 $caption_type = null;
1491 $caption_lang = null;
1492 $caption_startTime = null;
1493 $caption_endTime = null;
1494 $caption_text = null;
1495 if (isset($caption['attribs']['']['type'])) {
1496 $caption_type = $this->sanitize($caption['attribs']['']['type'], \SimplePie\SimplePie::CONSTRUCT_TEXT);
1497 }
1498 if (isset($caption['attribs']['']['lang'])) {
1499 $caption_lang = $this->sanitize($caption['attribs']['']['lang'], \SimplePie\SimplePie::CONSTRUCT_TEXT);
1500 }
1501 if (isset($caption['attribs']['']['start'])) {
1502 $caption_startTime = $this->sanitize($caption['attribs']['']['start'], \SimplePie\SimplePie::CONSTRUCT_TEXT);
1503 }
1504 if (isset($caption['attribs']['']['end'])) {
1505 $caption_endTime = $this->sanitize($caption['attribs']['']['end'], \SimplePie\SimplePie::CONSTRUCT_TEXT);
1506 }
1507 if (isset($caption['data'])) {
1508 $caption_text = $this->sanitize($caption['data'], \SimplePie\SimplePie::CONSTRUCT_TEXT);
1509 }
1510 $captions[] = $this->registry->create(Caption::class, [$caption_type, $caption_lang, $caption_startTime, $caption_endTime, $caption_text]);
1511 }
1512 if (is_array($captions)) {
1513 $captions = array_values(array_unique($captions));
1514 }
1515 } elseif (isset($group['child'][\SimplePie\SimplePie::NAMESPACE_MEDIARSS]['text'])) {
1516 foreach ($group['child'][\SimplePie\SimplePie::NAMESPACE_MEDIARSS]['text'] as $caption) {
1517 $caption_type = null;
1518 $caption_lang = null;
1519 $caption_startTime = null;
1520 $caption_endTime = null;
1521 $caption_text = null;
1522 if (isset($caption['attribs']['']['type'])) {
1523 $caption_type = $this->sanitize($caption['attribs']['']['type'], \SimplePie\SimplePie::CONSTRUCT_TEXT);
1524 }
1525 if (isset($caption['attribs']['']['lang'])) {
1526 $caption_lang = $this->sanitize($caption['attribs']['']['lang'], \SimplePie\SimplePie::CONSTRUCT_TEXT);
1527 }
1528 if (isset($caption['attribs']['']['start'])) {
1529 $caption_startTime = $this->sanitize($caption['attribs']['']['start'], \SimplePie\SimplePie::CONSTRUCT_TEXT);
1530 }
1531 if (isset($caption['attribs']['']['end'])) {
1532 $caption_endTime = $this->sanitize($caption['attribs']['']['end'], \SimplePie\SimplePie::CONSTRUCT_TEXT);
1533 }
1534 if (isset($caption['data'])) {
1535 $caption_text = $this->sanitize($caption['data'], \SimplePie\SimplePie::CONSTRUCT_TEXT);
1536 }
1537 $captions[] = $this->registry->create(Caption::class, [$caption_type, $caption_lang, $caption_startTime, $caption_endTime, $caption_text]);
1538 }
1539 if (is_array($captions)) {
1540 $captions = array_values(array_unique($captions));
1541 }
1542 } else {
1543 $captions = $captions_parent;
1544 }
1545
1546 // CATEGORIES
1547 if (isset($content['child'][\SimplePie\SimplePie::NAMESPACE_MEDIARSS]['category'])) {
1548 foreach ((array) $content['child'][\SimplePie\SimplePie::NAMESPACE_MEDIARSS]['category'] as $category) {
1549 $term = null;
1550 $scheme = null;
1551 $label = null;
1552 if (isset($category['data'])) {
1553 $term = $this->sanitize($category['data'], \SimplePie\SimplePie::CONSTRUCT_TEXT);
1554 }
1555 if (isset($category['attribs']['']['scheme'])) {
1556 $scheme = $this->sanitize($category['attribs']['']['scheme'], \SimplePie\SimplePie::CONSTRUCT_TEXT);
1557 } else {
1558 $scheme = 'http://search.yahoo.com/mrss/category_schema';
1559 }
1560 if (isset($category['attribs']['']['label'])) {
1561 $label = $this->sanitize($category['attribs']['']['label'], \SimplePie\SimplePie::CONSTRUCT_TEXT);
1562 }
1563 $categories[] = $this->registry->create(Category::class, [$term, $scheme, $label]);
1564 }
1565 }
1566 if (isset($group['child'][\SimplePie\SimplePie::NAMESPACE_MEDIARSS]['category'])) {
1567 foreach ((array) $group['child'][\SimplePie\SimplePie::NAMESPACE_MEDIARSS]['category'] as $category) {
1568 $term = null;
1569 $scheme = null;
1570 $label = null;
1571 if (isset($category['data'])) {
1572 $term = $this->sanitize($category['data'], \SimplePie\SimplePie::CONSTRUCT_TEXT);
1573 }
1574 if (isset($category['attribs']['']['scheme'])) {
1575 $scheme = $this->sanitize($category['attribs']['']['scheme'], \SimplePie\SimplePie::CONSTRUCT_TEXT);
1576 } else {
1577 $scheme = 'http://search.yahoo.com/mrss/category_schema';
1578 }
1579 if (isset($category['attribs']['']['label'])) {
1580 $label = $this->sanitize($category['attribs']['']['label'], \SimplePie\SimplePie::CONSTRUCT_TEXT);
1581 }
1582 $categories[] = $this->registry->create(Category::class, [$term, $scheme, $label]);
1583 }
1584 }
1585 if (is_array($categories) && is_array($categories_parent)) {
1586 $categories = array_values(array_unique(array_merge($categories, $categories_parent)));
1587 } elseif (is_array($categories)) {
1588 $categories = array_values(array_unique($categories));
1589 } elseif (is_array($categories_parent)) {
1590 $categories = array_values(array_unique($categories_parent));
1591 }
1592
1593 // COPYRIGHTS
1594 if (isset($content['child'][\SimplePie\SimplePie::NAMESPACE_MEDIARSS]['copyright'])) {
1595 $copyright_url = null;
1596 $copyright_label = null;
1597 if (isset($content['child'][\SimplePie\SimplePie::NAMESPACE_MEDIARSS]['copyright'][0]['attribs']['']['url'])) {
1598 $copyright_url = $this->sanitize($content['child'][\SimplePie\SimplePie::NAMESPACE_MEDIARSS]['copyright'][0]['attribs']['']['url'], \SimplePie\SimplePie::CONSTRUCT_TEXT);
1599 }
1600 if (isset($content['child'][\SimplePie\SimplePie::NAMESPACE_MEDIARSS]['copyright'][0]['data'])) {
1601 $copyright_label = $this->sanitize($content['child'][\SimplePie\SimplePie::NAMESPACE_MEDIARSS]['copyright'][0]['data'], \SimplePie\SimplePie::CONSTRUCT_TEXT);
1602 }
1603 $copyrights = $this->registry->create(Copyright::class, [$copyright_url, $copyright_label]);
1604 } elseif (isset($group['child'][\SimplePie\SimplePie::NAMESPACE_MEDIARSS]['copyright'])) {
1605 $copyright_url = null;
1606 $copyright_label = null;
1607 if (isset($group['child'][\SimplePie\SimplePie::NAMESPACE_MEDIARSS]['copyright'][0]['attribs']['']['url'])) {
1608 $copyright_url = $this->sanitize($group['child'][\SimplePie\SimplePie::NAMESPACE_MEDIARSS]['copyright'][0]['attribs']['']['url'], \SimplePie\SimplePie::CONSTRUCT_TEXT);
1609 }
1610 if (isset($group['child'][\SimplePie\SimplePie::NAMESPACE_MEDIARSS]['copyright'][0]['data'])) {
1611 $copyright_label = $this->sanitize($group['child'][\SimplePie\SimplePie::NAMESPACE_MEDIARSS]['copyright'][0]['data'], \SimplePie\SimplePie::CONSTRUCT_TEXT);
1612 }
1613 $copyrights = $this->registry->create(Copyright::class, [$copyright_url, $copyright_label]);
1614 } else {
1615 $copyrights = $copyrights_parent;
1616 }
1617
1618 // CREDITS
1619 if (isset($content['child'][\SimplePie\SimplePie::NAMESPACE_MEDIARSS]['credit'])) {
1620 foreach ($content['child'][\SimplePie\SimplePie::NAMESPACE_MEDIARSS]['credit'] as $credit) {
1621 $credit_role = null;
1622 $credit_scheme = null;
1623 $credit_name = null;
1624 if (isset($credit['attribs']['']['role'])) {
1625 $credit_role = $this->sanitize($credit['attribs']['']['role'], \SimplePie\SimplePie::CONSTRUCT_TEXT);
1626 }
1627 if (isset($credit['attribs']['']['scheme'])) {
1628 $credit_scheme = $this->sanitize($credit['attribs']['']['scheme'], \SimplePie\SimplePie::CONSTRUCT_TEXT);
1629 } else {
1630 $credit_scheme = 'urn:ebu';
1631 }
1632 if (isset($credit['data'])) {
1633 $credit_name = $this->sanitize($credit['data'], \SimplePie\SimplePie::CONSTRUCT_TEXT);
1634 }
1635 $credits[] = $this->registry->create(Credit::class, [$credit_role, $credit_scheme, $credit_name]);
1636 }
1637 if (is_array($credits)) {
1638 $credits = array_values(array_unique($credits));
1639 }
1640 } elseif (isset($group['child'][\SimplePie\SimplePie::NAMESPACE_MEDIARSS]['credit'])) {
1641 foreach ($group['child'][\SimplePie\SimplePie::NAMESPACE_MEDIARSS]['credit'] as $credit) {
1642 $credit_role = null;
1643 $credit_scheme = null;
1644 $credit_name = null;
1645 if (isset($credit['attribs']['']['role'])) {
1646 $credit_role = $this->sanitize($credit['attribs']['']['role'], \SimplePie\SimplePie::CONSTRUCT_TEXT);
1647 }
1648 if (isset($credit['attribs']['']['scheme'])) {
1649 $credit_scheme = $this->sanitize($credit['attribs']['']['scheme'], \SimplePie\SimplePie::CONSTRUCT_TEXT);
1650 } else {
1651 $credit_scheme = 'urn:ebu';
1652 }
1653 if (isset($credit['data'])) {
1654 $credit_name = $this->sanitize($credit['data'], \SimplePie\SimplePie::CONSTRUCT_TEXT);
1655 }
1656 $credits[] = $this->registry->create(Credit::class, [$credit_role, $credit_scheme, $credit_name]);
1657 }
1658 if (is_array($credits)) {
1659 $credits = array_values(array_unique($credits));
1660 }
1661 } else {
1662 $credits = $credits_parent;
1663 }
1664
1665 // DESCRIPTION
1666 if (isset($content['child'][\SimplePie\SimplePie::NAMESPACE_MEDIARSS]['description'])) {
1667 $description = $this->sanitize($content['child'][\SimplePie\SimplePie::NAMESPACE_MEDIARSS]['description'][0]['data'], \SimplePie\SimplePie::CONSTRUCT_TEXT);
1668 } elseif (isset($group['child'][\SimplePie\SimplePie::NAMESPACE_MEDIARSS]['description'])) {
1669 $description = $this->sanitize($group['child'][\SimplePie\SimplePie::NAMESPACE_MEDIARSS]['description'][0]['data'], \SimplePie\SimplePie::CONSTRUCT_TEXT);
1670 } else {
1671 $description = $description_parent;
1672 }
1673
1674 // HASHES
1675 if (isset($content['child'][\SimplePie\SimplePie::NAMESPACE_MEDIARSS]['hash'])) {
1676 foreach ($content['child'][\SimplePie\SimplePie::NAMESPACE_MEDIARSS]['hash'] as $hash) {
1677 $value = null;
1678 $algo = null;
1679 if (isset($hash['data'])) {
1680 $value = $this->sanitize($hash['data'], \SimplePie\SimplePie::CONSTRUCT_TEXT);
1681 }
1682 if (isset($hash['attribs']['']['algo'])) {
1683 $algo = $this->sanitize($hash['attribs']['']['algo'], \SimplePie\SimplePie::CONSTRUCT_TEXT);
1684 } else {
1685 $algo = 'md5';
1686 }
1687 $hashes[] = $algo.':'.$value;
1688 }
1689 if (is_array($hashes)) {
1690 $hashes = array_values(array_unique($hashes));
1691 }
1692 } elseif (isset($group['child'][\SimplePie\SimplePie::NAMESPACE_MEDIARSS]['hash'])) {
1693 foreach ($group['child'][\SimplePie\SimplePie::NAMESPACE_MEDIARSS]['hash'] as $hash) {
1694 $value = null;
1695 $algo = null;
1696 if (isset($hash['data'])) {
1697 $value = $this->sanitize($hash['data'], \SimplePie\SimplePie::CONSTRUCT_TEXT);
1698 }
1699 if (isset($hash['attribs']['']['algo'])) {
1700 $algo = $this->sanitize($hash['attribs']['']['algo'], \SimplePie\SimplePie::CONSTRUCT_TEXT);
1701 } else {
1702 $algo = 'md5';
1703 }
1704 $hashes[] = $algo.':'.$value;
1705 }
1706 if (is_array($hashes)) {
1707 $hashes = array_values(array_unique($hashes));
1708 }
1709 } else {
1710 $hashes = $hashes_parent;
1711 }
1712
1713 // KEYWORDS
1714 if (isset($content['child'][\SimplePie\SimplePie::NAMESPACE_MEDIARSS]['keywords'])) {
1715 if (isset($content['child'][\SimplePie\SimplePie::NAMESPACE_MEDIARSS]['keywords'][0]['data'])) {
1716 $temp = explode(',', $this->sanitize($content['child'][\SimplePie\SimplePie::NAMESPACE_MEDIARSS]['keywords'][0]['data'], \SimplePie\SimplePie::CONSTRUCT_TEXT));
1717 foreach ($temp as $word) {
1718 $keywords[] = trim($word);
1719 }
1720 unset($temp);
1721 }
1722 if (is_array($keywords)) {
1723 $keywords = array_values(array_unique($keywords));
1724 }
1725 } elseif (isset($group['child'][\SimplePie\SimplePie::NAMESPACE_MEDIARSS]['keywords'])) {
1726 if (isset($group['child'][\SimplePie\SimplePie::NAMESPACE_MEDIARSS]['keywords'][0]['data'])) {
1727 $temp = explode(',', $this->sanitize($group['child'][\SimplePie\SimplePie::NAMESPACE_MEDIARSS]['keywords'][0]['data'], \SimplePie\SimplePie::CONSTRUCT_TEXT));
1728 foreach ($temp as $word) {
1729 $keywords[] = trim($word);
1730 }
1731 unset($temp);
1732 }
1733 if (is_array($keywords)) {
1734 $keywords = array_values(array_unique($keywords));
1735 }
1736 } else {
1737 $keywords = $keywords_parent;
1738 }
1739
1740 // PLAYER
1741 if (isset($content['child'][\SimplePie\SimplePie::NAMESPACE_MEDIARSS]['player'])) {
1742 $playerElem = $content['child'][\SimplePie\SimplePie::NAMESPACE_MEDIARSS]['player'][0];
1743 $player = $this->sanitize($playerElem['attribs']['']['url'], \SimplePie\SimplePie::CONSTRUCT_IRI, $this->get_own_base($playerElem));
1744 } elseif (isset($group['child'][\SimplePie\SimplePie::NAMESPACE_MEDIARSS]['player'])) {
1745 $playerElem = $group['child'][\SimplePie\SimplePie::NAMESPACE_MEDIARSS]['player'][0];
1746 $player = $this->sanitize($playerElem['attribs']['']['url'], \SimplePie\SimplePie::CONSTRUCT_IRI, $this->get_own_base($playerElem));
1747 } else {
1748 $player = $player_parent;
1749 }
1750
1751 // RATINGS
1752 if (isset($content['child'][\SimplePie\SimplePie::NAMESPACE_MEDIARSS]['rating'])) {
1753 foreach ($content['child'][\SimplePie\SimplePie::NAMESPACE_MEDIARSS]['rating'] as $rating) {
1754 $rating_scheme = null;
1755 $rating_value = null;
1756 if (isset($rating['attribs']['']['scheme'])) {
1757 $rating_scheme = $this->sanitize($rating['attribs']['']['scheme'], \SimplePie\SimplePie::CONSTRUCT_TEXT);
1758 } else {
1759 $rating_scheme = 'urn:simple';
1760 }
1761 if (isset($rating['data'])) {
1762 $rating_value = $this->sanitize($rating['data'], \SimplePie\SimplePie::CONSTRUCT_TEXT);
1763 }
1764 $ratings[] = $this->registry->create(Rating::class, [$rating_scheme, $rating_value]);
1765 }
1766 if (is_array($ratings)) {
1767 $ratings = array_values(array_unique($ratings));
1768 }
1769 } elseif (isset($group['child'][\SimplePie\SimplePie::NAMESPACE_MEDIARSS]['rating'])) {
1770 foreach ($group['child'][\SimplePie\SimplePie::NAMESPACE_MEDIARSS]['rating'] as $rating) {
1771 $rating_scheme = null;
1772 $rating_value = null;
1773 if (isset($rating['attribs']['']['scheme'])) {
1774 $rating_scheme = $this->sanitize($rating['attribs']['']['scheme'], \SimplePie\SimplePie::CONSTRUCT_TEXT);
1775 } else {
1776 $rating_scheme = 'urn:simple';
1777 }
1778 if (isset($rating['data'])) {
1779 $rating_value = $this->sanitize($rating['data'], \SimplePie\SimplePie::CONSTRUCT_TEXT);
1780 }
1781 $ratings[] = $this->registry->create(Rating::class, [$rating_scheme, $rating_value]);
1782 }
1783 if (is_array($ratings)) {
1784 $ratings = array_values(array_unique($ratings));
1785 }
1786 } else {
1787 $ratings = $ratings_parent;
1788 }
1789
1790 // RESTRICTIONS
1791 if (isset($content['child'][\SimplePie\SimplePie::NAMESPACE_MEDIARSS]['restriction'])) {
1792 foreach ($content['child'][\SimplePie\SimplePie::NAMESPACE_MEDIARSS]['restriction'] as $restriction) {
1793 $restriction_relationship = null;
1794 $restriction_type = null;
1795 $restriction_value = null;
1796 if (isset($restriction['attribs']['']['relationship'])) {
1797 $restriction_relationship = $this->sanitize($restriction['attribs']['']['relationship'], \SimplePie\SimplePie::CONSTRUCT_TEXT);
1798 }
1799 if (isset($restriction['attribs']['']['type'])) {
1800 $restriction_type = $this->sanitize($restriction['attribs']['']['type'], \SimplePie\SimplePie::CONSTRUCT_TEXT);
1801 }
1802 if (isset($restriction['data'])) {
1803 $restriction_value = $this->sanitize($restriction['data'], \SimplePie\SimplePie::CONSTRUCT_TEXT);
1804 }
1805 $restrictions[] = $this->registry->create(Restriction::class, [$restriction_relationship, $restriction_type, $restriction_value]);
1806 }
1807 if (is_array($restrictions)) {
1808 $restrictions = array_values(array_unique($restrictions));
1809 }
1810 } elseif (isset($group['child'][\SimplePie\SimplePie::NAMESPACE_MEDIARSS]['restriction'])) {
1811 foreach ($group['child'][\SimplePie\SimplePie::NAMESPACE_MEDIARSS]['restriction'] as $restriction) {
1812 $restriction_relationship = null;
1813 $restriction_type = null;
1814 $restriction_value = null;
1815 if (isset($restriction['attribs']['']['relationship'])) {
1816 $restriction_relationship = $this->sanitize($restriction['attribs']['']['relationship'], \SimplePie\SimplePie::CONSTRUCT_TEXT);
1817 }
1818 if (isset($restriction['attribs']['']['type'])) {
1819 $restriction_type = $this->sanitize($restriction['attribs']['']['type'], \SimplePie\SimplePie::CONSTRUCT_TEXT);
1820 }
1821 if (isset($restriction['data'])) {
1822 $restriction_value = $this->sanitize($restriction['data'], \SimplePie\SimplePie::CONSTRUCT_TEXT);
1823 }
1824 $restrictions[] = $this->registry->create(Restriction::class, [$restriction_relationship, $restriction_type, $restriction_value]);
1825 }
1826 if (is_array($restrictions)) {
1827 $restrictions = array_values(array_unique($restrictions));
1828 }
1829 } else {
1830 $restrictions = $restrictions_parent;
1831 }
1832
1833 // THUMBNAILS
1834 if (isset($content['child'][\SimplePie\SimplePie::NAMESPACE_MEDIARSS]['thumbnail'])) {
1835 foreach ($content['child'][\SimplePie\SimplePie::NAMESPACE_MEDIARSS]['thumbnail'] as $thumbnail) {
1836 $thumbnails[] = $this->sanitize($thumbnail['attribs']['']['url'], \SimplePie\SimplePie::CONSTRUCT_IRI, $this->get_own_base($thumbnail));
1837 }
1838 if (is_array($thumbnails)) {
1839 $thumbnails = array_values(array_unique($thumbnails));
1840 }
1841 } elseif (isset($group['child'][\SimplePie\SimplePie::NAMESPACE_MEDIARSS]['thumbnail'])) {
1842 foreach ($group['child'][\SimplePie\SimplePie::NAMESPACE_MEDIARSS]['thumbnail'] as $thumbnail) {
1843 $thumbnails[] = $this->sanitize($thumbnail['attribs']['']['url'], \SimplePie\SimplePie::CONSTRUCT_IRI, $this->get_own_base($thumbnail));
1844 }
1845 if (is_array($thumbnails)) {
1846 $thumbnails = array_values(array_unique($thumbnails));
1847 }
1848 } else {
1849 $thumbnails = $thumbnails_parent;
1850 }
1851
1852 // TITLES
1853 if (isset($content['child'][\SimplePie\SimplePie::NAMESPACE_MEDIARSS]['title'])) {
1854 $title = $this->sanitize($content['child'][\SimplePie\SimplePie::NAMESPACE_MEDIARSS]['title'][0]['data'], \SimplePie\SimplePie::CONSTRUCT_TEXT);
1855 } elseif (isset($group['child'][\SimplePie\SimplePie::NAMESPACE_MEDIARSS]['title'])) {
1856 $title = $this->sanitize($group['child'][\SimplePie\SimplePie::NAMESPACE_MEDIARSS]['title'][0]['data'], \SimplePie\SimplePie::CONSTRUCT_TEXT);
1857 } else {
1858 $title = $title_parent;
1859 }
1860
1861 $this->data['enclosures'][] = $this->registry->create(Enclosure::class, [$url, $type, $length, null, $bitrate, $captions, $categories, $channels, $copyrights, $credits, $description, $duration, $expression, $framerate, $hashes, $height, $keywords, $lang, $medium, $player, $ratings, $restrictions, $samplingrate, $thumbnails, $title, $width]);
1862 }
1863 }
1864 }
1865 }
1866
1867 // If we have standalone media:content tags, loop through them.
1868 if (isset($this->data['child'][\SimplePie\SimplePie::NAMESPACE_MEDIARSS]['content'])) {
1869 foreach ((array) $this->data['child'][\SimplePie\SimplePie::NAMESPACE_MEDIARSS]['content'] as $content) {
1870 if (isset($content['attribs']['']['url']) || isset($content['child'][\SimplePie\SimplePie::NAMESPACE_MEDIARSS]['player'])) {
1871 // Attributes
1872 $bitrate = null;
1873 $channels = null;
1874 $duration = null;
1875 $expression = null;
1876 $framerate = null;
1877 $height = null;
1878 $javascript = null;
1879 $lang = null;
1880 $length = null;
1881 $medium = null;
1882 $samplingrate = null;
1883 $type = null;
1884 $url = null;
1885 $width = null;
1886
1887 // Elements
1888 $captions = null;
1889 $categories = null;
1890 $copyrights = null;
1891 $credits = null;
1892 $description = null;
1893 $hashes = null;
1894 $keywords = null;
1895 $player = null;
1896 $ratings = null;
1897 $restrictions = null;
1898 $thumbnails = null;
1899 $title = null;
1900
1901 // Start checking the attributes of media:content
1902 if (isset($content['attribs']['']['bitrate'])) {
1903 $bitrate = $this->sanitize($content['attribs']['']['bitrate'], \SimplePie\SimplePie::CONSTRUCT_TEXT);
1904 }
1905 if (isset($content['attribs']['']['channels'])) {
1906 $channels = $this->sanitize($content['attribs']['']['channels'], \SimplePie\SimplePie::CONSTRUCT_TEXT);
1907 }
1908 if (isset($content['attribs']['']['duration'])) {
1909 $duration = $this->sanitize($content['attribs']['']['duration'], \SimplePie\SimplePie::CONSTRUCT_TEXT);
1910 } else {
1911 $duration = $duration_parent;
1912 }
1913 if (isset($content['attribs']['']['expression'])) {
1914 $expression = $this->sanitize($content['attribs']['']['expression'], \SimplePie\SimplePie::CONSTRUCT_TEXT);
1915 }
1916 if (isset($content['attribs']['']['framerate'])) {
1917 $framerate = $this->sanitize($content['attribs']['']['framerate'], \SimplePie\SimplePie::CONSTRUCT_TEXT);
1918 }
1919 if (isset($content['attribs']['']['height'])) {
1920 $height = $this->sanitize($content['attribs']['']['height'], \SimplePie\SimplePie::CONSTRUCT_TEXT);
1921 }
1922 if (isset($content['attribs']['']['lang'])) {
1923 $lang = $this->sanitize($content['attribs']['']['lang'], \SimplePie\SimplePie::CONSTRUCT_TEXT);
1924 }
1925 if (isset($content['attribs']['']['fileSize'])) {
1926 $length = intval($content['attribs']['']['fileSize']);
1927 }
1928 if (isset($content['attribs']['']['medium'])) {
1929 $medium = $this->sanitize($content['attribs']['']['medium'], \SimplePie\SimplePie::CONSTRUCT_TEXT);
1930 }
1931 if (isset($content['attribs']['']['samplingrate'])) {
1932 $samplingrate = $this->sanitize($content['attribs']['']['samplingrate'], \SimplePie\SimplePie::CONSTRUCT_TEXT);
1933 }
1934 if (isset($content['attribs']['']['type'])) {
1935 $type = $this->sanitize($content['attribs']['']['type'], \SimplePie\SimplePie::CONSTRUCT_TEXT);
1936 }
1937 if (isset($content['attribs']['']['width'])) {
1938 $width = $this->sanitize($content['attribs']['']['width'], \SimplePie\SimplePie::CONSTRUCT_TEXT);
1939 }
1940 if (isset($content['attribs']['']['url'])) {
1941 $url = $this->sanitize($content['attribs']['']['url'], \SimplePie\SimplePie::CONSTRUCT_IRI, $this->get_own_base($content));
1942 }
1943 // Checking the other optional media: elements. Priority: media:content, media:group, item, channel
1944
1945 // CAPTIONS
1946 if (isset($content['child'][\SimplePie\SimplePie::NAMESPACE_MEDIARSS]['text'])) {
1947 foreach ($content['child'][\SimplePie\SimplePie::NAMESPACE_MEDIARSS]['text'] as $caption) {
1948 $caption_type = null;
1949 $caption_lang = null;
1950 $caption_startTime = null;
1951 $caption_endTime = null;
1952 $caption_text = null;
1953 if (isset($caption['attribs']['']['type'])) {
1954 $caption_type = $this->sanitize($caption['attribs']['']['type'], \SimplePie\SimplePie::CONSTRUCT_TEXT);
1955 }
1956 if (isset($caption['attribs']['']['lang'])) {
1957 $caption_lang = $this->sanitize($caption['attribs']['']['lang'], \SimplePie\SimplePie::CONSTRUCT_TEXT);
1958 }
1959 if (isset($caption['attribs']['']['start'])) {
1960 $caption_startTime = $this->sanitize($caption['attribs']['']['start'], \SimplePie\SimplePie::CONSTRUCT_TEXT);
1961 }
1962 if (isset($caption['attribs']['']['end'])) {
1963 $caption_endTime = $this->sanitize($caption['attribs']['']['end'], \SimplePie\SimplePie::CONSTRUCT_TEXT);
1964 }
1965 if (isset($caption['data'])) {
1966 $caption_text = $this->sanitize($caption['data'], \SimplePie\SimplePie::CONSTRUCT_TEXT);
1967 }
1968 $captions[] = $this->registry->create(Caption::class, [$caption_type, $caption_lang, $caption_startTime, $caption_endTime, $caption_text]);
1969 }
1970 if (is_array($captions)) {
1971 $captions = array_values(array_unique($captions));
1972 }
1973 } else {
1974 $captions = $captions_parent;
1975 }
1976
1977 // CATEGORIES
1978 if (isset($content['child'][\SimplePie\SimplePie::NAMESPACE_MEDIARSS]['category'])) {
1979 foreach ((array) $content['child'][\SimplePie\SimplePie::NAMESPACE_MEDIARSS]['category'] as $category) {
1980 $term = null;
1981 $scheme = null;
1982 $label = null;
1983 if (isset($category['data'])) {
1984 $term = $this->sanitize($category['data'], \SimplePie\SimplePie::CONSTRUCT_TEXT);
1985 }
1986 if (isset($category['attribs']['']['scheme'])) {
1987 $scheme = $this->sanitize($category['attribs']['']['scheme'], \SimplePie\SimplePie::CONSTRUCT_TEXT);
1988 } else {
1989 $scheme = 'http://search.yahoo.com/mrss/category_schema';
1990 }
1991 if (isset($category['attribs']['']['label'])) {
1992 $label = $this->sanitize($category['attribs']['']['label'], \SimplePie\SimplePie::CONSTRUCT_TEXT);
1993 }
1994 $categories[] = $this->registry->create(Category::class, [$term, $scheme, $label]);
1995 }
1996 }
1997 if (is_array($categories) && is_array($categories_parent)) {
1998 $categories = array_values(array_unique(array_merge($categories, $categories_parent)));
1999 } elseif (is_array($categories)) {
2000 $categories = array_values(array_unique($categories));
2001 } elseif (is_array($categories_parent)) {
2002 $categories = array_values(array_unique($categories_parent));
2003 } else {
2004 $categories = null;
2005 }
2006
2007 // COPYRIGHTS
2008 if (isset($content['child'][\SimplePie\SimplePie::NAMESPACE_MEDIARSS]['copyright'])) {
2009 $copyright_url = null;
2010 $copyright_label = null;
2011 if (isset($content['child'][\SimplePie\SimplePie::NAMESPACE_MEDIARSS]['copyright'][0]['attribs']['']['url'])) {
2012 $copyright_url = $this->sanitize($content['child'][\SimplePie\SimplePie::NAMESPACE_MEDIARSS]['copyright'][0]['attribs']['']['url'], \SimplePie\SimplePie::CONSTRUCT_TEXT);
2013 }
2014 if (isset($content['child'][\SimplePie\SimplePie::NAMESPACE_MEDIARSS]['copyright'][0]['data'])) {
2015 $copyright_label = $this->sanitize($content['child'][\SimplePie\SimplePie::NAMESPACE_MEDIARSS]['copyright'][0]['data'], \SimplePie\SimplePie::CONSTRUCT_TEXT);
2016 }
2017 $copyrights = $this->registry->create(Copyright::class, [$copyright_url, $copyright_label]);
2018 } else {
2019 $copyrights = $copyrights_parent;
2020 }
2021
2022 // CREDITS
2023 if (isset($content['child'][\SimplePie\SimplePie::NAMESPACE_MEDIARSS]['credit'])) {
2024 foreach ($content['child'][\SimplePie\SimplePie::NAMESPACE_MEDIARSS]['credit'] as $credit) {
2025 $credit_role = null;
2026 $credit_scheme = null;
2027 $credit_name = null;
2028 if (isset($credit['attribs']['']['role'])) {
2029 $credit_role = $this->sanitize($credit['attribs']['']['role'], \SimplePie\SimplePie::CONSTRUCT_TEXT);
2030 }
2031 if (isset($credit['attribs']['']['scheme'])) {
2032 $credit_scheme = $this->sanitize($credit['attribs']['']['scheme'], \SimplePie\SimplePie::CONSTRUCT_TEXT);
2033 } else {
2034 $credit_scheme = 'urn:ebu';
2035 }
2036 if (isset($credit['data'])) {
2037 $credit_name = $this->sanitize($credit['data'], \SimplePie\SimplePie::CONSTRUCT_TEXT);
2038 }
2039 $credits[] = $this->registry->create(Credit::class, [$credit_role, $credit_scheme, $credit_name]);
2040 }
2041 if (is_array($credits)) {
2042 $credits = array_values(array_unique($credits));
2043 }
2044 } else {
2045 $credits = $credits_parent;
2046 }
2047
2048 // DESCRIPTION
2049 if (isset($content['child'][\SimplePie\SimplePie::NAMESPACE_MEDIARSS]['description'])) {
2050 $description = $this->sanitize($content['child'][\SimplePie\SimplePie::NAMESPACE_MEDIARSS]['description'][0]['data'], \SimplePie\SimplePie::CONSTRUCT_TEXT);
2051 } else {
2052 $description = $description_parent;
2053 }
2054
2055 // HASHES
2056 if (isset($content['child'][\SimplePie\SimplePie::NAMESPACE_MEDIARSS]['hash'])) {
2057 foreach ($content['child'][\SimplePie\SimplePie::NAMESPACE_MEDIARSS]['hash'] as $hash) {
2058 $value = null;
2059 $algo = null;
2060 if (isset($hash['data'])) {
2061 $value = $this->sanitize($hash['data'], \SimplePie\SimplePie::CONSTRUCT_TEXT);
2062 }
2063 if (isset($hash['attribs']['']['algo'])) {
2064 $algo = $this->sanitize($hash['attribs']['']['algo'], \SimplePie\SimplePie::CONSTRUCT_TEXT);
2065 } else {
2066 $algo = 'md5';
2067 }
2068 $hashes[] = $algo.':'.$value;
2069 }
2070 if (is_array($hashes)) {
2071 $hashes = array_values(array_unique($hashes));
2072 }
2073 } else {
2074 $hashes = $hashes_parent;
2075 }
2076
2077 // KEYWORDS
2078 if (isset($content['child'][\SimplePie\SimplePie::NAMESPACE_MEDIARSS]['keywords'])) {
2079 if (isset($content['child'][\SimplePie\SimplePie::NAMESPACE_MEDIARSS]['keywords'][0]['data'])) {
2080 $temp = explode(',', $this->sanitize($content['child'][\SimplePie\SimplePie::NAMESPACE_MEDIARSS]['keywords'][0]['data'], \SimplePie\SimplePie::CONSTRUCT_TEXT));
2081 foreach ($temp as $word) {
2082 $keywords[] = trim($word);
2083 }
2084 unset($temp);
2085 }
2086 if (is_array($keywords)) {
2087 $keywords = array_values(array_unique($keywords));
2088 }
2089 } else {
2090 $keywords = $keywords_parent;
2091 }
2092
2093 // PLAYER
2094 if (isset($content['child'][\SimplePie\SimplePie::NAMESPACE_MEDIARSS]['player'])) {
2095 if (isset($content['child'][\SimplePie\SimplePie::NAMESPACE_MEDIARSS]['player'][0]['attribs']['']['url'])) {
2096 $playerElem = $content['child'][\SimplePie\SimplePie::NAMESPACE_MEDIARSS]['player'][0];
2097 $player = $this->sanitize($playerElem['attribs']['']['url'], \SimplePie\SimplePie::CONSTRUCT_IRI, $this->get_own_base($playerElem));
2098 }
2099 } else {
2100 $player = $player_parent;
2101 }
2102
2103 // RATINGS
2104 if (isset($content['child'][\SimplePie\SimplePie::NAMESPACE_MEDIARSS]['rating'])) {
2105 foreach ($content['child'][\SimplePie\SimplePie::NAMESPACE_MEDIARSS]['rating'] as $rating) {
2106 $rating_scheme = null;
2107 $rating_value = null;
2108 if (isset($rating['attribs']['']['scheme'])) {
2109 $rating_scheme = $this->sanitize($rating['attribs']['']['scheme'], \SimplePie\SimplePie::CONSTRUCT_TEXT);
2110 } else {
2111 $rating_scheme = 'urn:simple';
2112 }
2113 if (isset($rating['data'])) {
2114 $rating_value = $this->sanitize($rating['data'], \SimplePie\SimplePie::CONSTRUCT_TEXT);
2115 }
2116 $ratings[] = $this->registry->create(Rating::class, [$rating_scheme, $rating_value]);
2117 }
2118 if (is_array($ratings)) {
2119 $ratings = array_values(array_unique($ratings));
2120 }
2121 } else {
2122 $ratings = $ratings_parent;
2123 }
2124
2125 // RESTRICTIONS
2126 if (isset($content['child'][\SimplePie\SimplePie::NAMESPACE_MEDIARSS]['restriction'])) {
2127 foreach ($content['child'][\SimplePie\SimplePie::NAMESPACE_MEDIARSS]['restriction'] as $restriction) {
2128 $restriction_relationship = null;
2129 $restriction_type = null;
2130 $restriction_value = null;
2131 if (isset($restriction['attribs']['']['relationship'])) {
2132 $restriction_relationship = $this->sanitize($restriction['attribs']['']['relationship'], \SimplePie\SimplePie::CONSTRUCT_TEXT);
2133 }
2134 if (isset($restriction['attribs']['']['type'])) {
2135 $restriction_type = $this->sanitize($restriction['attribs']['']['type'], \SimplePie\SimplePie::CONSTRUCT_TEXT);
2136 }
2137 if (isset($restriction['data'])) {
2138 $restriction_value = $this->sanitize($restriction['data'], \SimplePie\SimplePie::CONSTRUCT_TEXT);
2139 }
2140 $restrictions[] = $this->registry->create(Restriction::class, [$restriction_relationship, $restriction_type, $restriction_value]);
2141 }
2142 if (is_array($restrictions)) {
2143 $restrictions = array_values(array_unique($restrictions));
2144 }
2145 } else {
2146 $restrictions = $restrictions_parent;
2147 }
2148
2149 // THUMBNAILS
2150 if (isset($content['child'][\SimplePie\SimplePie::NAMESPACE_MEDIARSS]['thumbnail'])) {
2151 foreach ($content['child'][\SimplePie\SimplePie::NAMESPACE_MEDIARSS]['thumbnail'] as $thumbnail) {
2152 if (isset($thumbnail['attribs']['']['url'])) {
2153 $thumbnails[] = $this->sanitize($thumbnail['attribs']['']['url'], \SimplePie\SimplePie::CONSTRUCT_IRI, $this->get_own_base($thumbnail));
2154 }
2155 }
2156 if (is_array($thumbnails)) {
2157 $thumbnails = array_values(array_unique($thumbnails));
2158 }
2159 } else {
2160 $thumbnails = $thumbnails_parent;
2161 }
2162
2163 // TITLES
2164 if (isset($content['child'][\SimplePie\SimplePie::NAMESPACE_MEDIARSS]['title'])) {
2165 $title = $this->sanitize($content['child'][\SimplePie\SimplePie::NAMESPACE_MEDIARSS]['title'][0]['data'], \SimplePie\SimplePie::CONSTRUCT_TEXT);
2166 } else {
2167 $title = $title_parent;
2168 }
2169
2170 $this->data['enclosures'][] = $this->registry->create(Enclosure::class, [$url, $type, $length, null, $bitrate, $captions, $categories, $channels, $copyrights, $credits, $description, $duration, $expression, $framerate, $hashes, $height, $keywords, $lang, $medium, $player, $ratings, $restrictions, $samplingrate, $thumbnails, $title, $width]);
2171 }
2172 }
2173 }
2174
2175 foreach ((array) $this->get_item_tags(\SimplePie\SimplePie::NAMESPACE_ATOM_10, 'link') as $link) {
2176 if (isset($link['attribs']['']['href']) && !empty($link['attribs']['']['rel']) && $link['attribs']['']['rel'] === 'enclosure') {
2177 // Attributes
2178 $bitrate = null;
2179 $channels = null;
2180 $duration = null;
2181 $expression = null;
2182 $framerate = null;
2183 $height = null;
2184 $javascript = null;
2185 $lang = null;
2186 $length = null;
2187 $medium = null;
2188 $samplingrate = null;
2189 $type = null;
2190 $url = null;
2191 $width = null;
2192
2193 $url = $this->sanitize($link['attribs']['']['href'], \SimplePie\SimplePie::CONSTRUCT_IRI, $this->get_own_base($link));
2194 if (isset($link['attribs']['']['type'])) {
2195 $type = $this->sanitize($link['attribs']['']['type'], \SimplePie\SimplePie::CONSTRUCT_TEXT);
2196 }
2197 if (isset($link['attribs']['']['length'])) {
2198 $length = intval($link['attribs']['']['length']);
2199 }
2200 if (isset($link['attribs']['']['title'])) {
2201 $title = $this->sanitize($link['attribs']['']['title'], \SimplePie\SimplePie::CONSTRUCT_TEXT);
2202 } else {
2203 $title = $title_parent;
2204 }
2205
2206 // Since we don't have group or content for these, we'll just pass the '*_parent' variables directly to the constructor
2207 $this->data['enclosures'][] = $this->registry->create(Enclosure::class, [$url, $type, $length, null, $bitrate, $captions_parent, $categories_parent, $channels, $copyrights_parent, $credits_parent, $description_parent, $duration_parent, $expression, $framerate, $hashes_parent, $height, $keywords_parent, $lang, $medium, $player_parent, $ratings_parent, $restrictions_parent, $samplingrate, $thumbnails_parent, $title, $width]);
2208 }
2209 }
2210
2211 foreach ((array) $this->get_item_tags(\SimplePie\SimplePie::NAMESPACE_ATOM_03, 'link') as $link) {
2212 if (isset($link['attribs']['']['href']) && !empty($link['attribs']['']['rel']) && $link['attribs']['']['rel'] === 'enclosure') {
2213 // Attributes
2214 $bitrate = null;
2215 $channels = null;
2216 $duration = null;
2217 $expression = null;
2218 $framerate = null;
2219 $height = null;
2220 $javascript = null;
2221 $lang = null;
2222 $length = null;
2223 $medium = null;
2224 $samplingrate = null;
2225 $type = null;
2226 $url = null;
2227 $width = null;
2228
2229 $url = $this->sanitize($link['attribs']['']['href'], \SimplePie\SimplePie::CONSTRUCT_IRI, $this->get_own_base($link));
2230 if (isset($link['attribs']['']['type'])) {
2231 $type = $this->sanitize($link['attribs']['']['type'], \SimplePie\SimplePie::CONSTRUCT_TEXT);
2232 }
2233 if (isset($link['attribs']['']['length'])) {
2234 $length = intval($link['attribs']['']['length']);
2235 }
2236
2237 // Since we don't have group or content for these, we'll just pass the '*_parent' variables directly to the constructor
2238 $this->data['enclosures'][] = $this->registry->create(Enclosure::class, [$url, $type, $length, null, $bitrate, $captions_parent, $categories_parent, $channels, $copyrights_parent, $credits_parent, $description_parent, $duration_parent, $expression, $framerate, $hashes_parent, $height, $keywords_parent, $lang, $medium, $player_parent, $ratings_parent, $restrictions_parent, $samplingrate, $thumbnails_parent, $title_parent, $width]);
2239 }
2240 }
2241
2242 foreach ($this->get_item_tags(\SimplePie\SimplePie::NAMESPACE_RSS_20, 'enclosure') ?? [] as $enclosure) {
2243 if (isset($enclosure['attribs']['']['url'])) {
2244 // Attributes
2245 $bitrate = null;
2246 $channels = null;
2247 $duration = null;
2248 $expression = null;
2249 $framerate = null;
2250 $height = null;
2251 $javascript = null;
2252 $lang = null;
2253 $length = null;
2254 $medium = null;
2255 $samplingrate = null;
2256 $type = null;
2257 $url = null;
2258 $width = null;
2259
2260 $url = $this->sanitize($enclosure['attribs']['']['url'], \SimplePie\SimplePie::CONSTRUCT_IRI, $this->get_own_base($enclosure));
2261 $url = $this->get_sanitize()->https_url($url);
2262 if (isset($enclosure['attribs']['']['type'])) {
2263 $type = $this->sanitize($enclosure['attribs']['']['type'], \SimplePie\SimplePie::CONSTRUCT_TEXT);
2264 }
2265 if (isset($enclosure['attribs']['']['length'])) {
2266 $length = intval($enclosure['attribs']['']['length']);
2267 }
2268
2269 // Since we don't have group or content for these, we'll just pass the '*_parent' variables directly to the constructor
2270 $this->data['enclosures'][] = $this->registry->create(Enclosure::class, [$url, $type, $length, null, $bitrate, $captions_parent, $categories_parent, $channels, $copyrights_parent, $credits_parent, $description_parent, $duration_parent, $expression, $framerate, $hashes_parent, $height, $keywords_parent, $lang, $medium, $player_parent, $ratings_parent, $restrictions_parent, $samplingrate, $thumbnails_parent, $title_parent, $width]);
2271 }
2272 }
2273
2274 if (count($this->data['enclosures']) === 0 && ($url || $type || $length || $bitrate || $captions_parent || $categories_parent || $channels || $copyrights_parent || $credits_parent || $description_parent || $duration_parent || $expression || $framerate || $hashes_parent || $height || $keywords_parent || $lang || $medium || $player_parent || $ratings_parent || $samplingrate || $thumbnails_parent || $title_parent || $width)) {
2275 // Since we don't have group or content for these, we'll just pass the '*_parent' variables directly to the constructor
2276 $this->data['enclosures'][] = $this->registry->create(Enclosure::class, [$url, $type, $length, null, $bitrate, $captions_parent, $categories_parent, $channels, $copyrights_parent, $credits_parent, $description_parent, $duration_parent, $expression, $framerate, $hashes_parent, $height, $keywords_parent, $lang, $medium, $player_parent, $ratings_parent, $restrictions_parent, $samplingrate, $thumbnails_parent, $title_parent, $width]);
2277 }
2278
2279 $this->data['enclosures'] = array_values(array_unique($this->data['enclosures']));
2280 }
2281 if (!empty($this->data['enclosures'])) {
2282 return $this->data['enclosures'];
2283 }
2284
2285 return null;
2286 }
2287
2288 /**
2289 * Get the latitude coordinates for the item
2290 *
2291 * Compatible with the W3C WGS84 Basic Geo and GeoRSS specifications
2292 *
2293 * Uses `<geo:lat>` or `<georss:point>`
2294 *
2295 * @since 1.0
2296 * @link http://www.w3.org/2003/01/geo/ W3C WGS84 Basic Geo
2297 * @link http://www.georss.org/ GeoRSS
2298 * @return float|null
2299 */
2300 public function get_latitude()
2301 {
2302 if ($return = $this->get_item_tags(\SimplePie\SimplePie::NAMESPACE_W3C_BASIC_GEO, 'lat')) {
2303 return (float) $return[0]['data'];
2304 } elseif (($return = $this->get_item_tags(\SimplePie\SimplePie::NAMESPACE_GEORSS, 'point')) && preg_match('/^((?:-)?[0-9]+(?:\.[0-9]+)) ((?:-)?[0-9]+(?:\.[0-9]+))$/', trim($return[0]['data']), $match)) {
2305 return (float) $match[1];
2306 }
2307
2308 return null;
2309 }
2310
2311 /**
2312 * Get the longitude coordinates for the item
2313 *
2314 * Compatible with the W3C WGS84 Basic Geo and GeoRSS specifications
2315 *
2316 * Uses `<geo:long>`, `<geo:lon>` or `<georss:point>`
2317 *
2318 * @since 1.0
2319 * @link http://www.w3.org/2003/01/geo/ W3C WGS84 Basic Geo
2320 * @link http://www.georss.org/ GeoRSS
2321 * @return float|null
2322 */
2323 public function get_longitude()
2324 {
2325 if ($return = $this->get_item_tags(\SimplePie\SimplePie::NAMESPACE_W3C_BASIC_GEO, 'long')) {
2326 return (float) $return[0]['data'];
2327 } elseif ($return = $this->get_item_tags(\SimplePie\SimplePie::NAMESPACE_W3C_BASIC_GEO, 'lon')) {
2328 return (float) $return[0]['data'];
2329 } elseif (($return = $this->get_item_tags(\SimplePie\SimplePie::NAMESPACE_GEORSS, 'point')) && preg_match('/^((?:-)?[0-9]+(?:\.[0-9]+)) ((?:-)?[0-9]+(?:\.[0-9]+))$/', trim($return[0]['data']), $match)) {
2330 return (float) $match[2];
2331 }
2332
2333 return null;
2334 }
2335
2336 /**
2337 * Get the `<atom:source>` for the item
2338 *
2339 * @since 1.1
2340 * @return \SimplePie\Source|null
2341 */
2342 public function get_source()
2343 {
2344 if ($return = $this->get_item_tags(\SimplePie\SimplePie::NAMESPACE_ATOM_10, 'source')) {
2345 return $this->registry->create(Source::class, [$this, $return[0]]);
2346 }
2347
2348 return null;
2349 }
2350
2351 public function set_sanitize(Sanitize $sanitize): void
2352 {
2353 $this->sanitize = $sanitize;
2354 }
2355
2356 protected function get_sanitize(): Sanitize
2357 {
2358 if ($this->sanitize === null) {
2359 $this->sanitize = new Sanitize();
2360 }
2361
2362 return $this->sanitize;
2363 }
2364}
2365
2366class_alias('SimplePie\Item', 'SimplePie_Item');
2367
Ui Ux Design – Teachers Night Out https://cardgames4educators.com Wed, 16 Oct 2024 22:24:18 +0000 en-US hourly 1 https://wordpress.org/?v=6.9.4 https://cardgames4educators.com/wp-content/uploads/2024/06/cropped-Card-4-Educators-logo-32x32.png Ui Ux Design – Teachers Night Out https://cardgames4educators.com 32 32 Masters In English How English Speaker https://cardgames4educators.com/masters-in-english-how-english-speaker/ https://cardgames4educators.com/masters-in-english-how-english-speaker/#comments Mon, 27 May 2024 08:54:45 +0000 https://themexriver.com/wp/kadu/?p=1

Erat himenaeos neque id sagittis massa. Hac suscipit pulvinar dignissim platea magnis eu. Don tellus a pharetra inceptos efficitur dui pulvinar. Feugiat facilisis penatibus pulvinar nunc dictumst donec odio platea habitasse. Lacus porta dolor purus elit ante bibendum tortor netus taciti nullam cubilia. Erat per suspendisse placerat morbi egestas pulvinar bibendum sollicitudin nec. Euismod cubilia eleifend velit himenaeos sodales lectus. Leo maximus cras ac porttitor aliquam torquent pulvinar odio volutpat parturient. Quisque risus finibus suspendisse mus purus magnis facilisi condimentum consectetur dui. Curae elit suspendisse cursus vehicula.

Turpis taciti class non vel pretium quis pulvinar tempor lobortis nunc. Libero phasellus parturient sapien volutpat malesuada ornare. Cubilia dignissim sollicitudin rhoncus lacinia maximus. Cras lorem fermentum bibendum pellentesque nisl etiam ligula enim cubilia. Vulputate pede sapien torquent montes tempus malesuada in mattis dis turpis vitae. Porta est tempor ex eget feugiat vulputate ipsum. Justo nec iaculis habitant diam arcu fermentum.

We offer comprehen sive emplo ment services such as assistance wit employer compliance.Our company is your strategic HR partner as instead of HR. john smithson

Cubilia dignissim sollicitudin rhoncus lacinia maximus. Cras lorem fermentum bibendum pellentesque nisl etiam ligula enim cubilia. Vulputate pede sapien torquent montes tempus malesuada in mattis dis turpis vitae.

Exploring Learning Landscapes in Academic

Feugiat facilisis penatibus pulvinar nunc dictumst donec odio platea habitasse. Lacus porta dolor purus elit ante bibendum tortor netus taciti nullam cubilia. Erat per suspendisse placerat morbi egestas pulvinar bibendum sollicitudin nec. Euismod cubilia eleifend velit himenaeos sodales lectus. Leo maximus cras ac porttitor aliquam torquent.

]]>
https://cardgames4educators.com/masters-in-english-how-english-speaker/feed/ 1