Issues (4967)

Security Analysis    not enabled

This project does not seem to handle request data directly as such no vulnerable execution paths were found.

  Cross-Site Scripting
Cross-Site Scripting enables an attacker to inject code into the response of a web-request that is viewed by other users. It can for example be used to bypass access controls, or even to take over other users' accounts.
  File Exposure
File Exposure allows an attacker to gain access to local files that he should not be able to access. These files can for example include database credentials, or other configuration files.
  File Manipulation
File Manipulation enables an attacker to write custom data to files. This potentially leads to injection of arbitrary code on the server.
  Object Injection
Object Injection enables an attacker to inject an object into PHP code, and can lead to arbitrary code execution, file exposure, or file manipulation attacks.
  Code Injection
Code Injection enables an attacker to execute arbitrary code on the server.
  Response Splitting
Response Splitting can be used to send arbitrary responses.
  File Inclusion
File Inclusion enables an attacker to inject custom files into PHP's file loading mechanism, either explicitly passed to include, or for example via PHP's auto-loading mechanism.
  Command Injection
Command Injection enables an attacker to inject a shell command that is execute with the privileges of the web-server. This can be used to expose sensitive data, or gain access of your server.
  SQL Injection
SQL Injection enables an attacker to execute arbitrary SQL code on your database server gaining access to user data, or manipulating user data.
  XPath Injection
XPath Injection enables an attacker to modify the parts of XML document that are read. If that XML document is for example used for authentication, this can lead to further vulnerabilities similar to SQL Injection.
  LDAP Injection
LDAP Injection enables an attacker to inject LDAP statements potentially granting permission to run unauthorized queries, or modify content inside the LDAP tree.
  Header Injection
  Other Vulnerability
This category comprises other attack vectors such as manipulating the PHP runtime, loading custom extensions, freezing the runtime, or similar.
  Regex Injection
Regex Injection enables an attacker to execute arbitrary code in your PHP process.
  XML Injection
XML Injection enables an attacker to read files on your local filesystem including configuration files, or can be abused to freeze your web-server process.
  Variable Injection
Variable Injection enables an attacker to overwrite program variables with custom data, and can lead to further vulnerabilities.
Unfortunately, the security analysis is currently not available for your project. If you are a non-commercial open-source project, please contact support to gain access.

src/wp-includes/class-simplepie.php (23 issues)

Upgrade to new PHP Analysis Engine

These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more

1
<?php
2
if ( ! class_exists( 'SimplePie', false ) ) :
3
4
// Load classes we will need.
5
require ABSPATH . WPINC . '/SimplePie/Misc.php';
6
require ABSPATH . WPINC . '/SimplePie/Cache.php';
7
require ABSPATH . WPINC . '/SimplePie/File.php';
8
require ABSPATH . WPINC . '/SimplePie/Sanitize.php';
9
require ABSPATH . WPINC . '/SimplePie/Registry.php';
10
require ABSPATH . WPINC . '/SimplePie/IRI.php';
11
require ABSPATH . WPINC . '/SimplePie/Locator.php';
12
require ABSPATH . WPINC . '/SimplePie/Content/Type/Sniffer.php';
13
require ABSPATH . WPINC . '/SimplePie/XML/Declaration/Parser.php';
14
require ABSPATH . WPINC . '/SimplePie/Parser.php';
15
require ABSPATH . WPINC . '/SimplePie/Item.php';
16
require ABSPATH . WPINC . '/SimplePie/Parse/Date.php';
17
require ABSPATH . WPINC . '/SimplePie/Author.php';
18
19
/**
20
 * WordPress autoloader for SimplePie.
21
 *
22
 * @since 3.5.0
23
 */
24
function wp_simplepie_autoload( $class ) {
25
	if ( 0 !== strpos( $class, 'SimplePie_' ) )
26
		return;
27
28
	$file = ABSPATH . WPINC . '/' . str_replace( '_', '/', $class ) . '.php';
29
	include( $file );
30
}
31
32
/**
33
 * We autoload classes we may not need.
34
 */
35
spl_autoload_register( 'wp_simplepie_autoload' );
36
37
/**
38
 * SimplePie
39
 *
40
 * A PHP-Based RSS and Atom Feed Framework.
41
 * Takes the hard work out of managing a complete RSS/Atom solution.
42
 *
43
 * Copyright (c) 2004-2012, Ryan Parman, Geoffrey Sneddon, Ryan McCue, and contributors
44
 * All rights reserved.
45
 *
46
 * Redistribution and use in source and binary forms, with or without modification, are
47
 * permitted provided that the following conditions are met:
48
 *
49
 * 	* Redistributions of source code must retain the above copyright notice, this list of
50
 * 	  conditions and the following disclaimer.
51
 *
52
 * 	* Redistributions in binary form must reproduce the above copyright notice, this list
53
 * 	  of conditions and the following disclaimer in the documentation and/or other materials
54
 * 	  provided with the distribution.
55
 *
56
 * 	* Neither the name of the SimplePie Team nor the names of its contributors may be used
57
 * 	  to endorse or promote products derived from this software without specific prior
58
 * 	  written permission.
59
 *
60
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS
61
 * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
62
 * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS
63
 * AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
64
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
65
 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
66
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
67
 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
68
 * POSSIBILITY OF SUCH DAMAGE.
69
 *
70
 * @package SimplePie
71
 * @version 1.3.1
72
 * @copyright 2004-2012 Ryan Parman, Geoffrey Sneddon, Ryan McCue
73
 * @author Ryan Parman
74
 * @author Geoffrey Sneddon
75
 * @author Ryan McCue
76
 * @link http://simplepie.org/ SimplePie
77
 * @license http://www.opensource.org/licenses/bsd-license.php BSD License
78
 */
79
80
/**
81
 * SimplePie Name
82
 */
83
define('SIMPLEPIE_NAME', 'SimplePie');
84
85
/**
86
 * SimplePie Version
87
 */
88
define('SIMPLEPIE_VERSION', '1.3.1');
89
90
/**
91
 * SimplePie Build
92
 * @todo Hardcode for release (there's no need to have to call SimplePie_Misc::get_build() only every load of simplepie.inc)
93
 */
94
define('SIMPLEPIE_BUILD', gmdate('YmdHis', SimplePie_Misc::get_build()));
95
96
/**
97
 * SimplePie Website URL
98
 */
99
define('SIMPLEPIE_URL', 'http://simplepie.org');
100
101
/**
102
 * SimplePie Useragent
103
 * @see SimplePie::set_useragent()
104
 */
105
define('SIMPLEPIE_USERAGENT', SIMPLEPIE_NAME . '/' . SIMPLEPIE_VERSION . ' (Feed Parser; ' . SIMPLEPIE_URL . '; Allow like Gecko) Build/' . SIMPLEPIE_BUILD);
106
107
/**
108
 * SimplePie Linkback
109
 */
110
define('SIMPLEPIE_LINKBACK', '<a href="' . SIMPLEPIE_URL . '" title="' . SIMPLEPIE_NAME . ' ' . SIMPLEPIE_VERSION . '">' . SIMPLEPIE_NAME . '</a>');
111
112
/**
113
 * No Autodiscovery
114
 * @see SimplePie::set_autodiscovery_level()
115
 */
116
define('SIMPLEPIE_LOCATOR_NONE', 0);
117
118
/**
119
 * Feed Link Element Autodiscovery
120
 * @see SimplePie::set_autodiscovery_level()
121
 */
122
define('SIMPLEPIE_LOCATOR_AUTODISCOVERY', 1);
123
124
/**
125
 * Local Feed Extension Autodiscovery
126
 * @see SimplePie::set_autodiscovery_level()
127
 */
128
define('SIMPLEPIE_LOCATOR_LOCAL_EXTENSION', 2);
129
130
/**
131
 * Local Feed Body Autodiscovery
132
 * @see SimplePie::set_autodiscovery_level()
133
 */
134
define('SIMPLEPIE_LOCATOR_LOCAL_BODY', 4);
135
136
/**
137
 * Remote Feed Extension Autodiscovery
138
 * @see SimplePie::set_autodiscovery_level()
139
 */
140
define('SIMPLEPIE_LOCATOR_REMOTE_EXTENSION', 8);
141
142
/**
143
 * Remote Feed Body Autodiscovery
144
 * @see SimplePie::set_autodiscovery_level()
145
 */
146
define('SIMPLEPIE_LOCATOR_REMOTE_BODY', 16);
147
148
/**
149
 * All Feed Autodiscovery
150
 * @see SimplePie::set_autodiscovery_level()
151
 */
152
define('SIMPLEPIE_LOCATOR_ALL', 31);
153
154
/**
155
 * No known feed type
156
 */
157
define('SIMPLEPIE_TYPE_NONE', 0);
158
159
/**
160
 * RSS 0.90
161
 */
162
define('SIMPLEPIE_TYPE_RSS_090', 1);
163
164
/**
165
 * RSS 0.91 (Netscape)
166
 */
167
define('SIMPLEPIE_TYPE_RSS_091_NETSCAPE', 2);
168
169
/**
170
 * RSS 0.91 (Userland)
171
 */
172
define('SIMPLEPIE_TYPE_RSS_091_USERLAND', 4);
173
174
/**
175
 * RSS 0.91 (both Netscape and Userland)
176
 */
177
define('SIMPLEPIE_TYPE_RSS_091', 6);
178
179
/**
180
 * RSS 0.92
181
 */
182
define('SIMPLEPIE_TYPE_RSS_092', 8);
183
184
/**
185
 * RSS 0.93
186
 */
187
define('SIMPLEPIE_TYPE_RSS_093', 16);
188
189
/**
190
 * RSS 0.94
191
 */
192
define('SIMPLEPIE_TYPE_RSS_094', 32);
193
194
/**
195
 * RSS 1.0
196
 */
197
define('SIMPLEPIE_TYPE_RSS_10', 64);
198
199
/**
200
 * RSS 2.0
201
 */
202
define('SIMPLEPIE_TYPE_RSS_20', 128);
203
204
/**
205
 * RDF-based RSS
206
 */
207
define('SIMPLEPIE_TYPE_RSS_RDF', 65);
208
209
/**
210
 * Non-RDF-based RSS (truly intended as syndication format)
211
 */
212
define('SIMPLEPIE_TYPE_RSS_SYNDICATION', 190);
213
214
/**
215
 * All RSS
216
 */
217
define('SIMPLEPIE_TYPE_RSS_ALL', 255);
218
219
/**
220
 * Atom 0.3
221
 */
222
define('SIMPLEPIE_TYPE_ATOM_03', 256);
223
224
/**
225
 * Atom 1.0
226
 */
227
define('SIMPLEPIE_TYPE_ATOM_10', 512);
228
229
/**
230
 * All Atom
231
 */
232
define('SIMPLEPIE_TYPE_ATOM_ALL', 768);
233
234
/**
235
 * All feed types
236
 */
237
define('SIMPLEPIE_TYPE_ALL', 1023);
238
239
/**
240
 * No construct
241
 */
242
define('SIMPLEPIE_CONSTRUCT_NONE', 0);
243
244
/**
245
 * Text construct
246
 */
247
define('SIMPLEPIE_CONSTRUCT_TEXT', 1);
248
249
/**
250
 * HTML construct
251
 */
252
define('SIMPLEPIE_CONSTRUCT_HTML', 2);
253
254
/**
255
 * XHTML construct
256
 */
257
define('SIMPLEPIE_CONSTRUCT_XHTML', 4);
258
259
/**
260
 * base64-encoded construct
261
 */
262
define('SIMPLEPIE_CONSTRUCT_BASE64', 8);
263
264
/**
265
 * IRI construct
266
 */
267
define('SIMPLEPIE_CONSTRUCT_IRI', 16);
268
269
/**
270
 * A construct that might be HTML
271
 */
272
define('SIMPLEPIE_CONSTRUCT_MAYBE_HTML', 32);
273
274
/**
275
 * All constructs
276
 */
277
define('SIMPLEPIE_CONSTRUCT_ALL', 63);
278
279
/**
280
 * Don't change case
281
 */
282
define('SIMPLEPIE_SAME_CASE', 1);
283
284
/**
285
 * Change to lowercase
286
 */
287
define('SIMPLEPIE_LOWERCASE', 2);
288
289
/**
290
 * Change to uppercase
291
 */
292
define('SIMPLEPIE_UPPERCASE', 4);
293
294
/**
295
 * PCRE for HTML attributes
296
 */
297
define('SIMPLEPIE_PCRE_HTML_ATTRIBUTE', '((?:[\x09\x0A\x0B\x0C\x0D\x20]+[^\x09\x0A\x0B\x0C\x0D\x20\x2F\x3E][^\x09\x0A\x0B\x0C\x0D\x20\x2F\x3D\x3E]*(?:[\x09\x0A\x0B\x0C\x0D\x20]*=[\x09\x0A\x0B\x0C\x0D\x20]*(?:"(?:[^"]*)"|\'(?:[^\']*)\'|(?:[^\x09\x0A\x0B\x0C\x0D\x20\x22\x27\x3E][^\x09\x0A\x0B\x0C\x0D\x20\x3E]*)?))?)*)[\x09\x0A\x0B\x0C\x0D\x20]*');
298
299
/**
300
 * PCRE for XML attributes
301
 */
302
define('SIMPLEPIE_PCRE_XML_ATTRIBUTE', '((?:\s+(?:(?:[^\s:]+:)?[^\s:]+)\s*=\s*(?:"(?:[^"]*)"|\'(?:[^\']*)\'))*)\s*');
303
304
/**
305
 * XML Namespace
306
 */
307
define('SIMPLEPIE_NAMESPACE_XML', 'http://www.w3.org/XML/1998/namespace');
308
309
/**
310
 * Atom 1.0 Namespace
311
 */
312
define('SIMPLEPIE_NAMESPACE_ATOM_10', 'http://www.w3.org/2005/Atom');
313
314
/**
315
 * Atom 0.3 Namespace
316
 */
317
define('SIMPLEPIE_NAMESPACE_ATOM_03', 'http://purl.org/atom/ns#');
318
319
/**
320
 * RDF Namespace
321
 */
322
define('SIMPLEPIE_NAMESPACE_RDF', 'http://www.w3.org/1999/02/22-rdf-syntax-ns#');
323
324
/**
325
 * RSS 0.90 Namespace
326
 */
327
define('SIMPLEPIE_NAMESPACE_RSS_090', 'http://my.netscape.com/rdf/simple/0.9/');
328
329
/**
330
 * RSS 1.0 Namespace
331
 */
332
define('SIMPLEPIE_NAMESPACE_RSS_10', 'http://purl.org/rss/1.0/');
333
334
/**
335
 * RSS 1.0 Content Module Namespace
336
 */
337
define('SIMPLEPIE_NAMESPACE_RSS_10_MODULES_CONTENT', 'http://purl.org/rss/1.0/modules/content/');
338
339
/**
340
 * RSS 2.0 Namespace
341
 * (Stupid, I know, but I'm certain it will confuse people less with support.)
342
 */
343
define('SIMPLEPIE_NAMESPACE_RSS_20', '');
344
345
/**
346
 * DC 1.0 Namespace
347
 */
348
define('SIMPLEPIE_NAMESPACE_DC_10', 'http://purl.org/dc/elements/1.0/');
349
350
/**
351
 * DC 1.1 Namespace
352
 */
353
define('SIMPLEPIE_NAMESPACE_DC_11', 'http://purl.org/dc/elements/1.1/');
354
355
/**
356
 * W3C Basic Geo (WGS84 lat/long) Vocabulary Namespace
357
 */
358
define('SIMPLEPIE_NAMESPACE_W3C_BASIC_GEO', 'http://www.w3.org/2003/01/geo/wgs84_pos#');
359
360
/**
361
 * GeoRSS Namespace
362
 */
363
define('SIMPLEPIE_NAMESPACE_GEORSS', 'http://www.georss.org/georss');
364
365
/**
366
 * Media RSS Namespace
367
 */
368
define('SIMPLEPIE_NAMESPACE_MEDIARSS', 'http://search.yahoo.com/mrss/');
369
370
/**
371
 * Wrong Media RSS Namespace. Caused by a long-standing typo in the spec.
372
 */
373
define('SIMPLEPIE_NAMESPACE_MEDIARSS_WRONG', 'http://search.yahoo.com/mrss');
374
375
/**
376
 * Wrong Media RSS Namespace #2. New namespace introduced in Media RSS 1.5.
377
 */
378
define('SIMPLEPIE_NAMESPACE_MEDIARSS_WRONG2', 'http://video.search.yahoo.com/mrss');
379
380
/**
381
 * Wrong Media RSS Namespace #3. A possible typo of the Media RSS 1.5 namespace.
382
 */
383
define('SIMPLEPIE_NAMESPACE_MEDIARSS_WRONG3', 'http://video.search.yahoo.com/mrss/');
384
385
/**
386
 * Wrong Media RSS Namespace #4. New spec location after the RSS Advisory Board takes it over, but not a valid namespace.
387
 */
388
define('SIMPLEPIE_NAMESPACE_MEDIARSS_WRONG4', 'http://www.rssboard.org/media-rss');
389
390
/**
391
 * Wrong Media RSS Namespace #5. A possible typo of the RSS Advisory Board URL.
392
 */
393
define('SIMPLEPIE_NAMESPACE_MEDIARSS_WRONG5', 'http://www.rssboard.org/media-rss/');
394
395
/**
396
 * iTunes RSS Namespace
397
 */
398
define('SIMPLEPIE_NAMESPACE_ITUNES', 'http://www.itunes.com/dtds/podcast-1.0.dtd');
399
400
/**
401
 * XHTML Namespace
402
 */
403
define('SIMPLEPIE_NAMESPACE_XHTML', 'http://www.w3.org/1999/xhtml');
404
405
/**
406
 * IANA Link Relations Registry
407
 */
408
define('SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY', 'http://www.iana.org/assignments/relation/');
409
410
/**
411
 * No file source
412
 */
413
define('SIMPLEPIE_FILE_SOURCE_NONE', 0);
414
415
/**
416
 * Remote file source
417
 */
418
define('SIMPLEPIE_FILE_SOURCE_REMOTE', 1);
419
420
/**
421
 * Local file source
422
 */
423
define('SIMPLEPIE_FILE_SOURCE_LOCAL', 2);
424
425
/**
426
 * fsockopen() file source
427
 */
428
define('SIMPLEPIE_FILE_SOURCE_FSOCKOPEN', 4);
429
430
/**
431
 * cURL file source
432
 */
433
define('SIMPLEPIE_FILE_SOURCE_CURL', 8);
434
435
/**
436
 * file_get_contents() file source
437
 */
438
define('SIMPLEPIE_FILE_SOURCE_FILE_GET_CONTENTS', 16);
439
440
441
442
/**
443
 * SimplePie
444
 *
445
 * @package SimplePie
446
 * @subpackage API
447
 */
448
class SimplePie
449
{
450
	/**
451
	 * @var array Raw data
452
	 * @access private
453
	 */
454
	public $data = array();
455
456
	/**
457
	 * @var mixed Error string
458
	 * @access private
459
	 */
460
	public $error;
461
462
	/**
463
	 * @var object Instance of SimplePie_Sanitize (or other class)
464
	 * @see SimplePie::set_sanitize_class()
465
	 * @access private
466
	 */
467
	public $sanitize;
468
469
	/**
470
	 * @var string SimplePie Useragent
471
	 * @see SimplePie::set_useragent()
472
	 * @access private
473
	 */
474
	public $useragent = SIMPLEPIE_USERAGENT;
475
476
	/**
477
	 * @var string Feed URL
478
	 * @see SimplePie::set_feed_url()
479
	 * @access private
480
	 */
481
	public $feed_url;
482
483
	/**
484
	 * @var object Instance of SimplePie_File to use as a feed
485
	 * @see SimplePie::set_file()
486
	 * @access private
487
	 */
488
	public $file;
489
490
	/**
491
	 * @var string Raw feed data
492
	 * @see SimplePie::set_raw_data()
493
	 * @access private
494
	 */
495
	public $raw_data;
496
497
	/**
498
	 * @var int Timeout for fetching remote files
499
	 * @see SimplePie::set_timeout()
500
	 * @access private
501
	 */
502
	public $timeout = 10;
503
504
	/**
505
	 * @var bool Forces fsockopen() to be used for remote files instead
506
	 * of cURL, even if a new enough version is installed
507
	 * @see SimplePie::force_fsockopen()
508
	 * @access private
509
	 */
510
	public $force_fsockopen = false;
511
512
	/**
513
	 * @var bool Force the given data/URL to be treated as a feed no matter what
514
	 * it appears like
515
	 * @see SimplePie::force_feed()
516
	 * @access private
517
	 */
518
	public $force_feed = false;
519
520
	/**
521
	 * @var bool Enable/Disable Caching
522
	 * @see SimplePie::enable_cache()
523
	 * @access private
524
	 */
525
	public $cache = true;
526
527
	/**
528
	 * @var int Cache duration (in seconds)
529
	 * @see SimplePie::set_cache_duration()
530
	 * @access private
531
	 */
532
	public $cache_duration = 3600;
533
534
	/**
535
	 * @var int Auto-discovery cache duration (in seconds)
536
	 * @see SimplePie::set_autodiscovery_cache_duration()
537
	 * @access private
538
	 */
539
	public $autodiscovery_cache_duration = 604800; // 7 Days.
540
541
	/**
542
	 * @var string Cache location (relative to executing script)
543
	 * @see SimplePie::set_cache_location()
544
	 * @access private
545
	 */
546
	public $cache_location = './cache';
547
548
	/**
549
	 * @var string Function that creates the cache filename
550
	 * @see SimplePie::set_cache_name_function()
551
	 * @access private
552
	 */
553
	public $cache_name_function = 'md5';
554
555
	/**
556
	 * @var bool Reorder feed by date descending
557
	 * @see SimplePie::enable_order_by_date()
558
	 * @access private
559
	 */
560
	public $order_by_date = true;
561
562
	/**
563
	 * @var mixed Force input encoding to be set to the follow value
564
	 * (false, or anything type-cast to false, disables this feature)
565
	 * @see SimplePie::set_input_encoding()
566
	 * @access private
567
	 */
568
	public $input_encoding = false;
569
570
	/**
571
	 * @var int Feed Autodiscovery Level
572
	 * @see SimplePie::set_autodiscovery_level()
573
	 * @access private
574
	 */
575
	public $autodiscovery = SIMPLEPIE_LOCATOR_ALL;
576
577
	/**
578
	 * Class registry object
579
	 *
580
	 * @var SimplePie_Registry
581
	 */
582
	public $registry;
583
584
	/**
585
	 * @var int Maximum number of feeds to check with autodiscovery
586
	 * @see SimplePie::set_max_checked_feeds()
587
	 * @access private
588
	 */
589
	public $max_checked_feeds = 10;
590
591
	/**
592
	 * @var array All the feeds found during the autodiscovery process
593
	 * @see SimplePie::get_all_discovered_feeds()
594
	 * @access private
595
	 */
596
	public $all_discovered_feeds = array();
597
598
	/**
599
	 * @var string Web-accessible path to the handler_image.php file.
600
	 * @see SimplePie::set_image_handler()
601
	 * @access private
602
	 */
603
	public $image_handler = '';
604
605
	/**
606
	 * @var array Stores the URLs when multiple feeds are being initialized.
607
	 * @see SimplePie::set_feed_url()
608
	 * @access private
609
	 */
610
	public $multifeed_url = array();
611
612
	/**
613
	 * @var array Stores SimplePie objects when multiple feeds initialized.
614
	 * @access private
615
	 */
616
	public $multifeed_objects = array();
617
618
	/**
619
	 * @var array Stores the get_object_vars() array for use with multifeeds.
620
	 * @see SimplePie::set_feed_url()
621
	 * @access private
622
	 */
623
	public $config_settings = null;
624
625
	/**
626
	 * @var integer Stores the number of items to return per-feed with multifeeds.
627
	 * @see SimplePie::set_item_limit()
628
	 * @access private
629
	 */
630
	public $item_limit = 0;
631
632
	/**
633
	 * @var array Stores the default attributes to be stripped by strip_attributes().
634
	 * @see SimplePie::strip_attributes()
635
	 * @access private
636
	 */
637
	public $strip_attributes = array('bgsound', 'class', 'expr', 'id', 'style', 'onclick', 'onerror', 'onfinish', 'onmouseover', 'onmouseout', 'onfocus', 'onblur', 'lowsrc', 'dynsrc');
638
639
	/**
640
	 * @var array Stores the default tags to be stripped by strip_htmltags().
641
	 * @see SimplePie::strip_htmltags()
642
	 * @access private
643
	 */
644
	public $strip_htmltags = array('base', 'blink', 'body', 'doctype', 'embed', 'font', 'form', 'frame', 'frameset', 'html', 'iframe', 'input', 'marquee', 'meta', 'noscript', 'object', 'param', 'script', 'style');
645
646
	/**
647
	 * The SimplePie class contains feed level data and options
648
	 *
649
	 * To use SimplePie, create the SimplePie object with no parameters. You can
650
	 * then set configuration options using the provided methods. After setting
651
	 * them, you must initialise the feed using $feed->init(). At that point the
652
	 * object's methods and properties will be available to you.
653
	 *
654
	 * Previously, it was possible to pass in the feed URL along with cache
655
	 * options directly into the constructor. This has been removed as of 1.3 as
656
	 * it caused a lot of confusion.
657
	 *
658
	 * @since 1.0 Preview Release
659
	 */
660
	public function __construct()
661
	{
662
		if (version_compare(PHP_VERSION, '5.2', '<'))
663
		{
664
			trigger_error('PHP 4.x, 5.0 and 5.1 are no longer supported. Please upgrade to PHP 5.2 or newer.');
665
			die();
0 ignored issues
show
Coding Style Compatibility introduced by
The method __construct() contains an exit expression.

An exit expression should only be used in rare cases. For example, if you write a short command line script.

In most cases however, using an exit expression makes the code untestable and often causes incompatibilities with other libraries. Thus, unless you are absolutely sure it is required here, we recommend to refactor your code to avoid its usage.

Loading history...
666
		}
667
668
		// Other objects, instances created here so we can set options on them
669
		$this->sanitize = new SimplePie_Sanitize();
670
		$this->registry = new SimplePie_Registry();
671
672
		if (func_num_args() > 0)
673
		{
674
			$level = defined('E_USER_DEPRECATED') ? E_USER_DEPRECATED : E_USER_WARNING;
675
			trigger_error('Passing parameters to the constructor is no longer supported. Please use set_feed_url(), set_cache_location(), and set_cache_location() directly.', $level);
676
677
			$args = func_get_args();
678
			switch (count($args)) {
679
				case 3:
680
					$this->set_cache_duration($args[2]);
681
				case 2:
682
					$this->set_cache_location($args[1]);
683
				case 1:
684
					$this->set_feed_url($args[0]);
685
					$this->init();
686
			}
687
		}
688
	}
689
690
	/**
691
	 * Used for converting object to a string
692
	 */
693
	public function __toString()
694
	{
695
		return md5(serialize($this->data));
696
	}
697
698
	/**
699
	 * Remove items that link back to this before destroying this object
700
	 */
701
	public function __destruct()
702
	{
703
		if ((version_compare(PHP_VERSION, '5.3', '<') || !gc_enabled()) && !ini_get('zend.ze1_compatibility_mode'))
704
		{
705 View Code Duplication
			if (!empty($this->data['items']))
706
			{
707
				foreach ($this->data['items'] as $item)
708
				{
709
					$item->__destruct();
710
				}
711
				unset($item, $this->data['items']);
712
			}
713 View Code Duplication
			if (!empty($this->data['ordered_items']))
714
			{
715
				foreach ($this->data['ordered_items'] as $item)
716
				{
717
					$item->__destruct();
718
				}
719
				unset($item, $this->data['ordered_items']);
720
			}
721
		}
722
	}
723
724
	/**
725
	 * Force the given data/URL to be treated as a feed
726
	 *
727
	 * This tells SimplePie to ignore the content-type provided by the server.
728
	 * Be careful when using this option, as it will also disable autodiscovery.
729
	 *
730
	 * @since 1.1
731
	 * @param bool $enable Force the given data/URL to be treated as a feed
732
	 */
733
	public function force_feed($enable = false)
734
	{
735
		$this->force_feed = (bool) $enable;
736
	}
737
738
	/**
739
	 * Set the URL of the feed you want to parse
740
	 *
741
	 * This allows you to enter the URL of the feed you want to parse, or the
742
	 * website you want to try to use auto-discovery on. This takes priority
743
	 * over any set raw data.
744
	 *
745
	 * You can set multiple feeds to mash together by passing an array instead
746
	 * of a string for the $url. Remember that with each additional feed comes
747
	 * additional processing and resources.
748
	 *
749
	 * @since 1.0 Preview Release
750
	 * @see set_raw_data()
751
	 * @param string|array $url This is the URL (or array of URLs) that you want to parse.
752
	 */
753
	public function set_feed_url($url)
754
	{
755
		$this->multifeed_url = array();
756
		if (is_array($url))
757
		{
758
			foreach ($url as $value)
759
			{
760
				$this->multifeed_url[] = $this->registry->call('Misc', 'fix_protocol', array($value, 1));
761
			}
762
		}
763
		else
764
		{
765
			$this->feed_url = $this->registry->call('Misc', 'fix_protocol', array($url, 1));
766
		}
767
	}
768
769
	/**
770
	 * Set an instance of {@see SimplePie_File} to use as a feed
771
	 *
772
	 * @param SimplePie_File &$file
773
	 * @return bool True on success, false on failure
774
	 */
775
	public function set_file(&$file)
776
	{
777
		if ($file instanceof SimplePie_File)
778
		{
779
			$this->feed_url = $file->url;
780
			$this->file =& $file;
781
			return true;
782
		}
783
		return false;
784
	}
785
786
	/**
787
	 * Set the raw XML data to parse
788
	 *
789
	 * Allows you to use a string of RSS/Atom data instead of a remote feed.
790
	 *
791
	 * If you have a feed available as a string in PHP, you can tell SimplePie
792
	 * to parse that data string instead of a remote feed. Any set feed URL
793
	 * takes precedence.
794
	 *
795
	 * @since 1.0 Beta 3
796
	 * @param string $data RSS or Atom data as a string.
797
	 * @see set_feed_url()
798
	 */
799
	public function set_raw_data($data)
800
	{
801
		$this->raw_data = $data;
802
	}
803
804
	/**
805
	 * Set the the default timeout for fetching remote feeds
806
	 *
807
	 * This allows you to change the maximum time the feed's server to respond
808
	 * and send the feed back.
809
	 *
810
	 * @since 1.0 Beta 3
811
	 * @param int $timeout The maximum number of seconds to spend waiting to retrieve a feed.
812
	 */
813
	public function set_timeout($timeout = 10)
814
	{
815
		$this->timeout = (int) $timeout;
816
	}
817
818
	/**
819
	 * Force SimplePie to use fsockopen() instead of cURL
820
	 *
821
	 * @since 1.0 Beta 3
822
	 * @param bool $enable Force fsockopen() to be used
823
	 */
824
	public function force_fsockopen($enable = false)
825
	{
826
		$this->force_fsockopen = (bool) $enable;
827
	}
828
829
	/**
830
	 * Enable/disable caching in SimplePie.
831
	 *
832
	 * This option allows you to disable caching all-together in SimplePie.
833
	 * However, disabling the cache can lead to longer load times.
834
	 *
835
	 * @since 1.0 Preview Release
836
	 * @param bool $enable Enable caching
837
	 */
838
	public function enable_cache($enable = true)
839
	{
840
		$this->cache = (bool) $enable;
841
	}
842
843
	/**
844
	 * Set the length of time (in seconds) that the contents of a feed will be
845
	 * cached
846
	 *
847
	 * @param int $seconds The feed content cache duration
848
	 */
849
	public function set_cache_duration($seconds = 3600)
850
	{
851
		$this->cache_duration = (int) $seconds;
852
	}
853
854
	/**
855
	 * Set the length of time (in seconds) that the autodiscovered feed URL will
856
	 * be cached
857
	 *
858
	 * @param int $seconds The autodiscovered feed URL cache duration.
859
	 */
860
	public function set_autodiscovery_cache_duration($seconds = 604800)
861
	{
862
		$this->autodiscovery_cache_duration = (int) $seconds;
863
	}
864
865
	/**
866
	 * Set the file system location where the cached files should be stored
867
	 *
868
	 * @param string $location The file system location.
869
	 */
870
	public function set_cache_location($location = './cache')
871
	{
872
		$this->cache_location = (string) $location;
873
	}
874
875
	/**
876
	 * Set whether feed items should be sorted into reverse chronological order
877
	 *
878
	 * @param bool $enable Sort as reverse chronological order.
879
	 */
880
	public function enable_order_by_date($enable = true)
881
	{
882
		$this->order_by_date = (bool) $enable;
883
	}
884
885
	/**
886
	 * Set the character encoding used to parse the feed
887
	 *
888
	 * This overrides the encoding reported by the feed, however it will fall
889
	 * back to the normal encoding detection if the override fails
890
	 *
891
	 * @param string $encoding Character encoding
892
	 */
893
	public function set_input_encoding($encoding = false)
894
	{
895
		if ($encoding)
0 ignored issues
show
Bug Best Practice introduced by
The expression $encoding of type false|string is loosely compared to true; this is ambiguous if the string can be empty. You might want to explicitly use !== false instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For string values, the empty string '' is a special case, in particular the following results might be unexpected:

''   == false // true
''   == null  // true
'ab' == false // false
'ab' == null  // false

// It is often better to use strict comparison
'' === false // false
'' === null  // false
Loading history...
896
		{
897
			$this->input_encoding = (string) $encoding;
898
		}
899
		else
900
		{
901
			$this->input_encoding = false;
902
		}
903
	}
904
905
	/**
906
	 * Set how much feed autodiscovery to do
907
	 *
908
	 * @see SIMPLEPIE_LOCATOR_NONE
909
	 * @see SIMPLEPIE_LOCATOR_AUTODISCOVERY
910
	 * @see SIMPLEPIE_LOCATOR_LOCAL_EXTENSION
911
	 * @see SIMPLEPIE_LOCATOR_LOCAL_BODY
912
	 * @see SIMPLEPIE_LOCATOR_REMOTE_EXTENSION
913
	 * @see SIMPLEPIE_LOCATOR_REMOTE_BODY
914
	 * @see SIMPLEPIE_LOCATOR_ALL
915
	 * @param int $level Feed Autodiscovery Level (level can be a combination of the above constants, see bitwise OR operator)
916
	 */
917
	public function set_autodiscovery_level($level = SIMPLEPIE_LOCATOR_ALL)
918
	{
919
		$this->autodiscovery = (int) $level;
920
	}
921
922
	/**
923
	 * Get the class registry
924
	 *
925
	 * Use this to override SimplePie's default classes
926
	 * @see SimplePie_Registry
927
	 * @return SimplePie_Registry
928
	 */
929
	public function &get_registry()
930
	{
931
		return $this->registry;
932
	}
933
934
	/**#@+
935
	 * Useful when you are overloading or extending SimplePie's default classes.
936
	 *
937
	 * @deprecated Use {@see get_registry()} instead
938
	 * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation
939
	 * @param string $class Name of custom class
940
	 * @return boolean True on success, false otherwise
941
	 */
942
	/**
943
	 * Set which class SimplePie uses for caching
944
	 */
945
	public function set_cache_class($class = 'SimplePie_Cache')
946
	{
947
		return $this->registry->register('Cache', $class, true);
948
	}
949
950
	/**
951
	 * Set which class SimplePie uses for auto-discovery
952
	 */
953
	public function set_locator_class($class = 'SimplePie_Locator')
954
	{
955
		return $this->registry->register('Locator', $class, true);
956
	}
957
958
	/**
959
	 * Set which class SimplePie uses for XML parsing
960
	 */
961
	public function set_parser_class($class = 'SimplePie_Parser')
962
	{
963
		return $this->registry->register('Parser', $class, true);
964
	}
965
966
	/**
967
	 * Set which class SimplePie uses for remote file fetching
968
	 */
969
	public function set_file_class($class = 'SimplePie_File')
970
	{
971
		return $this->registry->register('File', $class, true);
972
	}
973
974
	/**
975
	 * Set which class SimplePie uses for data sanitization
976
	 */
977
	public function set_sanitize_class($class = 'SimplePie_Sanitize')
978
	{
979
		return $this->registry->register('Sanitize', $class, true);
980
	}
981
982
	/**
983
	 * Set which class SimplePie uses for handling feed items
984
	 */
985
	public function set_item_class($class = 'SimplePie_Item')
986
	{
987
		return $this->registry->register('Item', $class, true);
988
	}
989
990
	/**
991
	 * Set which class SimplePie uses for handling author data
992
	 */
993
	public function set_author_class($class = 'SimplePie_Author')
994
	{
995
		return $this->registry->register('Author', $class, true);
996
	}
997
998
	/**
999
	 * Set which class SimplePie uses for handling category data
1000
	 */
1001
	public function set_category_class($class = 'SimplePie_Category')
1002
	{
1003
		return $this->registry->register('Category', $class, true);
1004
	}
1005
1006
	/**
1007
	 * Set which class SimplePie uses for feed enclosures
1008
	 */
1009
	public function set_enclosure_class($class = 'SimplePie_Enclosure')
1010
	{
1011
		return $this->registry->register('Enclosure', $class, true);
1012
	}
1013
1014
	/**
1015
	 * Set which class SimplePie uses for `<media:text>` captions
1016
	 */
1017
	public function set_caption_class($class = 'SimplePie_Caption')
1018
	{
1019
		return $this->registry->register('Caption', $class, true);
1020
	}
1021
1022
	/**
1023
	 * Set which class SimplePie uses for `<media:copyright>`
1024
	 */
1025
	public function set_copyright_class($class = 'SimplePie_Copyright')
1026
	{
1027
		return $this->registry->register('Copyright', $class, true);
1028
	}
1029
1030
	/**
1031
	 * Set which class SimplePie uses for `<media:credit>`
1032
	 */
1033
	public function set_credit_class($class = 'SimplePie_Credit')
1034
	{
1035
		return $this->registry->register('Credit', $class, true);
1036
	}
1037
1038
	/**
1039
	 * Set which class SimplePie uses for `<media:rating>`
1040
	 */
1041
	public function set_rating_class($class = 'SimplePie_Rating')
1042
	{
1043
		return $this->registry->register('Rating', $class, true);
1044
	}
1045
1046
	/**
1047
	 * Set which class SimplePie uses for `<media:restriction>`
1048
	 */
1049
	public function set_restriction_class($class = 'SimplePie_Restriction')
1050
	{
1051
		return $this->registry->register('Restriction', $class, true);
1052
	}
1053
1054
	/**
1055
	 * Set which class SimplePie uses for content-type sniffing
1056
	 */
1057
	public function set_content_type_sniffer_class($class = 'SimplePie_Content_Type_Sniffer')
1058
	{
1059
		return $this->registry->register('Content_Type_Sniffer', $class, true);
1060
	}
1061
1062
	/**
1063
	 * Set which class SimplePie uses item sources
1064
	 */
1065
	public function set_source_class($class = 'SimplePie_Source')
1066
	{
1067
		return $this->registry->register('Source', $class, true);
1068
	}
1069
	/**#@-*/
1070
1071
	/**
1072
	 * Set the user agent string
1073
	 *
1074
	 * @param string $ua New user agent string.
1075
	 */
1076
	public function set_useragent($ua = SIMPLEPIE_USERAGENT)
1077
	{
1078
		$this->useragent = (string) $ua;
1079
	}
1080
1081
	/**
1082
	 * Set callback function to create cache filename with
1083
	 *
1084
	 * @param mixed $function Callback function
1085
	 */
1086
	public function set_cache_name_function($function = 'md5')
1087
	{
1088
		if (is_callable($function))
1089
		{
1090
			$this->cache_name_function = $function;
0 ignored issues
show
Documentation Bug introduced by
It seems like $function of type callable is incompatible with the declared type string of property $cache_name_function.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
1091
		}
1092
	}
1093
1094
	/**
1095
	 * Set options to make SP as fast as possible
1096
	 *
1097
	 * Forgoes a substantial amount of data sanitization in favor of speed. This
1098
	 * turns SimplePie into a dumb parser of feeds.
1099
	 *
1100
	 * @param bool $set Whether to set them or not
1101
	 */
1102
	public function set_stupidly_fast($set = false)
1103
	{
1104
		if ($set)
1105
		{
1106
			$this->enable_order_by_date(false);
1107
			$this->remove_div(false);
1108
			$this->strip_comments(false);
1109
			$this->strip_htmltags(false);
1110
			$this->strip_attributes(false);
1111
			$this->set_image_handler(false);
1112
		}
1113
	}
1114
1115
	/**
1116
	 * Set maximum number of feeds to check with autodiscovery
1117
	 *
1118
	 * @param int $max Maximum number of feeds to check
1119
	 */
1120
	public function set_max_checked_feeds($max = 10)
1121
	{
1122
		$this->max_checked_feeds = (int) $max;
1123
	}
1124
1125
	public function remove_div($enable = true)
1126
	{
1127
		$this->sanitize->remove_div($enable);
1128
	}
1129
1130
	public function strip_htmltags($tags = '', $encode = null)
1131
	{
1132
		if ($tags === '')
1133
		{
1134
			$tags = $this->strip_htmltags;
1135
		}
1136
		$this->sanitize->strip_htmltags($tags);
1137
		if ($encode !== null)
1138
		{
1139
			$this->sanitize->encode_instead_of_strip($tags);
1140
		}
1141
	}
1142
1143
	public function encode_instead_of_strip($enable = true)
1144
	{
1145
		$this->sanitize->encode_instead_of_strip($enable);
1146
	}
1147
1148
	public function strip_attributes($attribs = '')
1149
	{
1150
		if ($attribs === '')
1151
		{
1152
			$attribs = $this->strip_attributes;
1153
		}
1154
		$this->sanitize->strip_attributes($attribs);
1155
	}
1156
1157
	/**
1158
	 * Set the output encoding
1159
	 *
1160
	 * Allows you to override SimplePie's output to match that of your webpage.
1161
	 * This is useful for times when your webpages are not being served as
1162
	 * UTF-8.  This setting will be obeyed by {@see handle_content_type()}, and
1163
	 * is similar to {@see set_input_encoding()}.
1164
	 *
1165
	 * It should be noted, however, that not all character encodings can support
1166
	 * all characters.  If your page is being served as ISO-8859-1 and you try
1167
	 * to display a Japanese feed, you'll likely see garbled characters.
1168
	 * Because of this, it is highly recommended to ensure that your webpages
1169
	 * are served as UTF-8.
1170
	 *
1171
	 * The number of supported character encodings depends on whether your web
1172
	 * host supports {@link http://php.net/mbstring mbstring},
1173
	 * {@link http://php.net/iconv iconv}, or both. See
1174
	 * {@link http://simplepie.org/wiki/faq/Supported_Character_Encodings} for
1175
	 * more information.
1176
	 *
1177
	 * @param string $encoding
1178
	 */
1179
	public function set_output_encoding($encoding = 'UTF-8')
1180
	{
1181
		$this->sanitize->set_output_encoding($encoding);
1182
	}
1183
1184
	public function strip_comments($strip = false)
1185
	{
1186
		$this->sanitize->strip_comments($strip);
1187
	}
1188
1189
	/**
1190
	 * Set element/attribute key/value pairs of HTML attributes
1191
	 * containing URLs that need to be resolved relative to the feed
1192
	 *
1193
	 * Defaults to |a|@href, |area|@href, |blockquote|@cite, |del|@cite,
1194
	 * |form|@action, |img|@longdesc, |img|@src, |input|@src, |ins|@cite,
1195
	 * |q|@cite
1196
	 *
1197
	 * @since 1.0
1198
	 * @param array|null $element_attribute Element/attribute key/value pairs, null for default
1199
	 */
1200
	public function set_url_replacements($element_attribute = null)
1201
	{
1202
		$this->sanitize->set_url_replacements($element_attribute);
1203
	}
1204
1205
	/**
1206
	 * Set the handler to enable the display of cached images.
1207
	 *
1208
	 * @param str $page Web-accessible path to the handler_image.php file.
1209
	 * @param str $qs The query string that the value should be passed to.
1210
	 */
1211
	public function set_image_handler($page = false, $qs = 'i')
1212
	{
1213
		if ($page !== false)
1214
		{
1215
			$this->sanitize->set_image_handler($page . '?' . $qs . '=');
1216
		}
1217
		else
1218
		{
1219
			$this->image_handler = '';
1220
		}
1221
	}
1222
1223
	/**
1224
	 * Set the limit for items returned per-feed with multifeeds
1225
	 *
1226
	 * @param integer $limit The maximum number of items to return.
1227
	 */
1228
	public function set_item_limit($limit = 0)
1229
	{
1230
		$this->item_limit = (int) $limit;
1231
	}
1232
1233
	/**
1234
	 * Initialize the feed object
1235
	 *
1236
	 * This is what makes everything happen.  Period.  This is where all of the
1237
	 * configuration options get processed, feeds are fetched, cached, and
1238
	 * parsed, and all of that other good stuff.
1239
	 *
1240
	 * @return boolean True if successful, false otherwise
1241
	 */
1242
	public function init()
1243
	{
1244
		// Check absolute bare minimum requirements.
1245
		if (!extension_loaded('xml') || !extension_loaded('pcre'))
1246
		{
1247
			return false;
1248
		}
1249
		// Then check the xml extension is sane (i.e., libxml 2.7.x issue on PHP < 5.2.9 and libxml 2.7.0 to 2.7.2 on any version) if we don't have xmlreader.
1250
		elseif (!extension_loaded('xmlreader'))
1251
		{
1252
			static $xml_is_sane = null;
1253 View Code Duplication
			if ($xml_is_sane === null)
1254
			{
1255
				$parser_check = xml_parser_create();
1256
				xml_parse_into_struct($parser_check, '<foo>&amp;</foo>', $values);
1257
				xml_parser_free($parser_check);
1258
				$xml_is_sane = isset($values[0]['value']);
1259
			}
1260
			if (!$xml_is_sane)
0 ignored issues
show
Bug Best Practice introduced by
The expression $xml_is_sane of type boolean|null is loosely compared to false; this is ambiguous if the boolean can be false. You might want to explicitly use !== null instead.

If an expression can have both false, and null as possible values. It is generally a good practice to always use strict comparison to clearly distinguish between those two values.

$a = canBeFalseAndNull();

// Instead of
if ( ! $a) { }

// Better use one of the explicit versions:
if ($a !== null) { }
if ($a !== false) { }
if ($a !== null && $a !== false) { }
Loading history...
1261
			{
1262
				return false;
1263
			}
1264
		}
1265
1266
		if (method_exists($this->sanitize, 'set_registry'))
1267
		{
1268
			$this->sanitize->set_registry($this->registry);
1269
		}
1270
1271
		// Pass whatever was set with config options over to the sanitizer.
1272
		// Pass the classes in for legacy support; new classes should use the registry instead
1273
		$this->sanitize->pass_cache_data($this->cache, $this->cache_location, $this->cache_name_function, $this->registry->get_class('Cache'));
1274
		$this->sanitize->pass_file_data($this->registry->get_class('File'), $this->timeout, $this->useragent, $this->force_fsockopen);
1275
1276
		if (!empty($this->multifeed_url))
1277
		{
1278
			$i = 0;
1279
			$success = 0;
1280
			$this->multifeed_objects = array();
1281
			$this->error = array();
1282
			foreach ($this->multifeed_url as $url)
1283
			{
1284
				$this->multifeed_objects[$i] = clone $this;
1285
				$this->multifeed_objects[$i]->set_feed_url($url);
1286
				$single_success = $this->multifeed_objects[$i]->init();
1287
				$success |= $single_success;
1288
				if (!$single_success)
1289
				{
1290
					$this->error[$i] = $this->multifeed_objects[$i]->error();
1291
				}
1292
				$i++;
1293
			}
1294
			return (bool) $success;
1295
		}
1296
		elseif ($this->feed_url === null && $this->raw_data === null)
1297
		{
1298
			return false;
1299
		}
1300
1301
		$this->error = null;
1302
		$this->data = array();
1303
		$this->multifeed_objects = array();
1304
		$cache = false;
1305
1306
		if ($this->feed_url !== null)
1307
		{
1308
			$parsed_feed_url = $this->registry->call('Misc', 'parse_url', array($this->feed_url));
1309
1310
			// Decide whether to enable caching
1311
			if ($this->cache && $parsed_feed_url['scheme'] !== '')
1312
			{
1313
				$cache = $this->registry->call('Cache', 'get_handler', array($this->cache_location, call_user_func($this->cache_name_function, $this->feed_url), 'spc'));
1314
			}
1315
1316
			// Fetch the data via SimplePie_File into $this->raw_data
1317
			if (($fetched = $this->fetch_data($cache)) === true)
1318
			{
1319
				return true;
1320
			}
1321
			elseif ($fetched === false) {
1322
				return false;
1323
			}
1324
1325
			list($headers, $sniffed) = $fetched;
1326
		}
1327
1328
		// Set up array of possible encodings
1329
		$encodings = array();
1330
1331
		// First check to see if input has been overridden.
1332
		if ($this->input_encoding !== false)
1333
		{
1334
			$encodings[] = $this->input_encoding;
1335
		}
1336
1337
		$application_types = array('application/xml', 'application/xml-dtd', 'application/xml-external-parsed-entity');
1338
		$text_types = array('text/xml', 'text/xml-external-parsed-entity');
1339
1340
		// RFC 3023 (only applies to sniffed content)
1341
		if (isset($sniffed))
1342
		{
1343
			if (in_array($sniffed, $application_types) || substr($sniffed, 0, 12) === 'application/' && substr($sniffed, -4) === '+xml')
1344
			{
1345 View Code Duplication
				if (isset($headers['content-type']) && preg_match('/;\x20?charset=([^;]*)/i', $headers['content-type'], $charset))
1346
				{
1347
					$encodings[] = strtoupper($charset[1]);
1348
				}
1349
				$encodings = array_merge($encodings, $this->registry->call('Misc', 'xml_encoding', array($this->raw_data, &$this->registry)));
1350
				$encodings[] = 'UTF-8';
1351
			}
1352
			elseif (in_array($sniffed, $text_types) || substr($sniffed, 0, 5) === 'text/' && substr($sniffed, -4) === '+xml')
1353
			{
1354 View Code Duplication
				if (isset($headers['content-type']) && preg_match('/;\x20?charset=([^;]*)/i', $headers['content-type'], $charset))
1355
				{
1356
					$encodings[] = $charset[1];
1357
				}
1358
				$encodings[] = 'US-ASCII';
1359
			}
1360
			// Text MIME-type default
1361
			elseif (substr($sniffed, 0, 5) === 'text/')
1362
			{
1363
				$encodings[] = 'US-ASCII';
1364
			}
1365
		}
1366
1367
		// Fallback to XML 1.0 Appendix F.1/UTF-8/ISO-8859-1
1368
		$encodings = array_merge($encodings, $this->registry->call('Misc', 'xml_encoding', array($this->raw_data, &$this->registry)));
1369
		$encodings[] = 'UTF-8';
1370
		$encodings[] = 'ISO-8859-1';
1371
1372
		// There's no point in trying an encoding twice
1373
		$encodings = array_unique($encodings);
1374
1375
		// Loop through each possible encoding, till we return something, or run out of possibilities
1376
		foreach ($encodings as $encoding)
1377
		{
1378
			// Change the encoding to UTF-8 (as we always use UTF-8 internally)
1379
			if ($utf8_data = $this->registry->call('Misc', 'change_encoding', array($this->raw_data, $encoding, 'UTF-8')))
1380
			{
1381
				// Create new parser
1382
				$parser = $this->registry->create('Parser');
1383
1384
				// If it's parsed fine
1385
				if ($parser->parse($utf8_data, 'UTF-8'))
1386
				{
1387
					$this->data = $parser->get_data();
1388
					if (!($this->get_type() & ~SIMPLEPIE_TYPE_NONE))
1389
					{
1390
						$this->error = "A feed could not be found at $this->feed_url. This does not appear to be a valid RSS or Atom feed.";
1391
						$this->registry->call('Misc', 'error', array($this->error, E_USER_NOTICE, __FILE__, __LINE__));
1392
						return false;
1393
					}
1394
1395
					if (isset($headers))
1396
					{
1397
						$this->data['headers'] = $headers;
1398
					}
1399
					$this->data['build'] = SIMPLEPIE_BUILD;
1400
1401
					// Cache the file if caching is enabled
1402
					if ($cache && !$cache->save($this))
0 ignored issues
show
The method save() does not seem to exist on object<SimplePie_Cache>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
1403
					{
1404
						trigger_error("$this->cache_location is not writeable. Make sure you've set the correct relative or absolute path, and that the location is server-writable.", E_USER_WARNING);
1405
					}
1406
					return true;
1407
				}
1408
			}
1409
		}
1410
1411
		if (isset($parser))
1412
		{
1413
			// We have an error, just set SimplePie_Misc::error to it and quit
1414
			$this->error = sprintf('This XML document is invalid, likely due to invalid characters. XML error: %s at line %d, column %d', $parser->get_error_string(), $parser->get_current_line(), $parser->get_current_column());
1415
		}
1416
		else
1417
		{
1418
			$this->error = 'The data could not be converted to UTF-8. You MUST have either the iconv or mbstring extension installed. Upgrading to PHP 5.x (which includes iconv) is highly recommended.';
1419
		}
1420
1421
		$this->registry->call('Misc', 'error', array($this->error, E_USER_NOTICE, __FILE__, __LINE__));
1422
1423
		return false;
1424
	}
1425
1426
	/**
1427
	 * Fetch the data via SimplePie_File
1428
	 *
1429
	 * If the data is already cached, attempt to fetch it from there instead
1430
	 * @param SimplePie_Cache|false $cache Cache handler, or false to not load from the cache
1431
	 * @return array|true Returns true if the data was loaded from the cache, or an array of HTTP headers and sniffed type
0 ignored issues
show
Should the return type not be boolean|array?

This check compares the return type specified in the @return annotation of a function or method doc comment with the types returned by the function and raises an issue if they mismatch.

Loading history...
1432
	 */
1433
	protected function fetch_data(&$cache)
1434
	{
1435
		// If it's enabled, use the cache
1436
		if ($cache)
1437
		{
1438
			// Load the Cache
1439
			$this->data = $cache->load();
0 ignored issues
show
The method load() does not seem to exist on object<SimplePie_Cache>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
1440
			if (!empty($this->data))
1441
			{
1442
				// If the cache is for an outdated build of SimplePie
1443
				if (!isset($this->data['build']) || $this->data['build'] !== SIMPLEPIE_BUILD)
1444
				{
1445
					$cache->unlink();
0 ignored issues
show
The method unlink() does not seem to exist on object<SimplePie_Cache>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
1446
					$this->data = array();
1447
				}
1448
				// If we've hit a collision just rerun it with caching disabled
1449
				elseif (isset($this->data['url']) && $this->data['url'] !== $this->feed_url)
1450
				{
1451
					$cache = false;
1452
					$this->data = array();
1453
				}
1454
				// If we've got a non feed_url stored (if the page isn't actually a feed, or is a redirect) use that URL.
1455
				elseif (isset($this->data['feed_url']))
1456
				{
1457
					// If the autodiscovery cache is still valid use it.
1458
					if ($cache->mtime() + $this->autodiscovery_cache_duration > time())
0 ignored issues
show
The method mtime() does not seem to exist on object<SimplePie_Cache>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
1459
					{
1460
						// Do not need to do feed autodiscovery yet.
1461
						if ($this->data['feed_url'] !== $this->data['url'])
1462
						{
1463
							$this->set_feed_url($this->data['feed_url']);
1464
							return $this->init();
1465
						}
1466
1467
						$cache->unlink();
0 ignored issues
show
The method unlink() does not seem to exist on object<SimplePie_Cache>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
1468
						$this->data = array();
1469
					}
1470
				}
1471
				// Check if the cache has been updated
1472
				elseif ($cache->mtime() + $this->cache_duration < time())
0 ignored issues
show
The method mtime() does not seem to exist on object<SimplePie_Cache>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
1473
				{
1474
					// If we have last-modified and/or etag set
1475
					if (isset($this->data['headers']['last-modified']) || isset($this->data['headers']['etag']))
1476
					{
1477
						$headers = array(
1478
							'Accept' => 'application/atom+xml, application/rss+xml, application/rdf+xml;q=0.9, application/xml;q=0.8, text/xml;q=0.8, text/html;q=0.7, unknown/unknown;q=0.1, application/unknown;q=0.1, */*;q=0.1',
1479
						);
1480
						if (isset($this->data['headers']['last-modified']))
1481
						{
1482
							$headers['if-modified-since'] = $this->data['headers']['last-modified'];
1483
						}
1484
						if (isset($this->data['headers']['etag']))
1485
						{
1486
							$headers['if-none-match'] = $this->data['headers']['etag'];
1487
						}
1488
1489
						$file = $this->registry->create('File', array($this->feed_url, $this->timeout/10, 5, $headers, $this->useragent, $this->force_fsockopen));
1490
1491
						if ($file->success)
1492
						{
1493
							if ($file->status_code === 304)
1494
							{
1495
								$cache->touch();
0 ignored issues
show
The method touch() does not seem to exist on object<SimplePie_Cache>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
1496
								return true;
1497
							}
1498
						}
1499
						else
1500
						{
1501
							unset($file);
1502
						}
1503
					}
1504
				}
1505
				// If the cache is still valid, just return true
1506
				else
1507
				{
1508
					$this->raw_data = false;
0 ignored issues
show
Documentation Bug introduced by
The property $raw_data was declared of type string, but false is of type false. Maybe add a type cast?

This check looks for assignments to scalar types that may be of the wrong type.

To ensure the code behaves as expected, it may be a good idea to add an explicit type cast.

$answer = 42;

$correct = false;

$correct = (bool) $answer;
Loading history...
1509
					return true;
1510
				}
1511
			}
1512
			// If the cache is empty, delete it
1513
			else
1514
			{
1515
				$cache->unlink();
0 ignored issues
show
The method unlink() does not seem to exist on object<SimplePie_Cache>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
1516
				$this->data = array();
1517
			}
1518
		}
1519
		// If we don't already have the file (it'll only exist if we've opened it to check if the cache has been modified), open it.
1520
		if (!isset($file))
1521
		{
1522
			if ($this->file instanceof SimplePie_File && $this->file->url === $this->feed_url)
1523
			{
1524
				$file =& $this->file;
1525
			}
1526
			else
1527
			{
1528
				$headers = array(
1529
					'Accept' => 'application/atom+xml, application/rss+xml, application/rdf+xml;q=0.9, application/xml;q=0.8, text/xml;q=0.8, text/html;q=0.7, unknown/unknown;q=0.1, application/unknown;q=0.1, */*;q=0.1',
1530
				);
1531
				$file = $this->registry->create('File', array($this->feed_url, $this->timeout, 5, $headers, $this->useragent, $this->force_fsockopen));
1532
			}
1533
		}
1534
		// If the file connection has an error, set SimplePie::error to that and quit
1535
		if (!$file->success && !($file->method & SIMPLEPIE_FILE_SOURCE_REMOTE === 0 || ($file->status_code === 200 || $file->status_code > 206 && $file->status_code < 300)))
1536
		{
1537
			$this->error = $file->error;
1538
			return !empty($this->data);
1539
		}
1540
1541
		if (!$this->force_feed)
1542
		{
1543
			// Check if the supplied URL is a feed, if it isn't, look for it.
1544
			$locate = $this->registry->create('Locator', array(&$file, $this->timeout, $this->useragent, $this->max_checked_feeds));
1545
1546
			if (!$locate->is_feed($file))
1547
			{
1548
				// We need to unset this so that if SimplePie::set_file() has been called that object is untouched
1549
				unset($file);
1550
				try
1551
				{
1552
					if (!($file = $locate->find($this->autodiscovery, $this->all_discovered_feeds)))
1553
					{
1554
						$this->error = "A feed could not be found at $this->feed_url. A feed with an invalid mime type may fall victim to this error, or " . SIMPLEPIE_NAME . " was unable to auto-discover it.. Use force_feed() if you are certain this URL is a real feed.";
1555
						$this->registry->call('Misc', 'error', array($this->error, E_USER_NOTICE, __FILE__, __LINE__));
1556
						return false;
1557
					}
1558
				}
1559
				catch (SimplePie_Exception $e)
1560
				{
1561
					// This is usually because DOMDocument doesn't exist
1562
					$this->error = $e->getMessage();
1563
					$this->registry->call('Misc', 'error', array($this->error, E_USER_NOTICE, $e->getFile(), $e->getLine()));
1564
					return false;
1565
				}
1566
				if ($cache)
1567
				{
1568
					$this->data = array('url' => $this->feed_url, 'feed_url' => $file->url, 'build' => SIMPLEPIE_BUILD);
1569
					if (!$cache->save($this))
0 ignored issues
show
The method save() does not seem to exist on object<SimplePie_Cache>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
1570
					{
1571
						trigger_error("$this->cache_location is not writeable. Make sure you've set the correct relative or absolute path, and that the location is server-writable.", E_USER_WARNING);
1572
					}
1573
					$cache = $this->registry->call('Cache', 'get_handler', array($this->cache_location, call_user_func($this->cache_name_function, $file->url), 'spc'));
1574
				}
1575
				$this->feed_url = $file->url;
1576
			}
1577
			$locate = null;
1578
		}
1579
1580
		$this->raw_data = $file->body;
1581
1582
		$headers = $file->headers;
1583
		$sniffer = $this->registry->create('Content_Type_Sniffer', array(&$file));
1584
		$sniffed = $sniffer->get_type();
1585
1586
		return array($headers, $sniffed);
1587
	}
1588
1589
	/**
1590
	 * Get the error message for the occurred error.
1591
	 *
1592
	 * @return string|array Error message, or array of messages for multifeeds
1593
	 */
1594
	public function error()
1595
	{
1596
		return $this->error;
1597
	}
1598
1599
	/**
1600
	 * Get the raw XML
1601
	 *
1602
	 * This is the same as the old `$feed->enable_xml_dump(true)`, but returns
1603
	 * the data instead of printing it.
1604
	 *
1605
	 * @return string|boolean Raw XML data, false if the cache is used
1606
	 */
1607
	public function get_raw_data()
1608
	{
1609
		return $this->raw_data;
1610
	}
1611
1612
	/**
1613
	 * Get the character encoding used for output
1614
	 *
1615
	 * @since Preview Release
1616
	 * @return string
1617
	 */
1618
	public function get_encoding()
1619
	{
1620
		return $this->sanitize->output_encoding;
1621
	}
1622
1623
	/**
1624
	 * Send the content-type header with correct encoding
1625
	 *
1626
	 * This method ensures that the SimplePie-enabled page is being served with
1627
	 * the correct {@link http://www.iana.org/assignments/media-types/ mime-type}
1628
	 * and character encoding HTTP headers (character encoding determined by the
1629
	 * {@see set_output_encoding} config option).
1630
	 *
1631
	 * This won't work properly if any content or whitespace has already been
1632
	 * sent to the browser, because it relies on PHP's
1633
	 * {@link http://php.net/header header()} function, and these are the
1634
	 * circumstances under which the function works.
1635
	 *
1636
	 * Because it's setting these settings for the entire page (as is the nature
1637
	 * of HTTP headers), this should only be used once per page (again, at the
1638
	 * top).
1639
	 *
1640
	 * @param string $mime MIME type to serve the page as
1641
	 */
1642
	public function handle_content_type($mime = 'text/html')
1643
	{
1644
		if (!headers_sent())
1645
		{
1646
			$header = "Content-type: $mime;";
1647
			if ($this->get_encoding())
1648
			{
1649
				$header .= ' charset=' . $this->get_encoding();
1650
			}
1651
			else
1652
			{
1653
				$header .= ' charset=UTF-8';
1654
			}
1655
			header($header);
1656
		}
1657
	}
1658
1659
	/**
1660
	 * Get the type of the feed
1661
	 *
1662
	 * This returns a SIMPLEPIE_TYPE_* constant, which can be tested against
1663
	 * using {@link http://php.net/language.operators.bitwise bitwise operators}
1664
	 *
1665
	 * @since 0.8 (usage changed to using constants in 1.0)
1666
	 * @see SIMPLEPIE_TYPE_NONE Unknown.
1667
	 * @see SIMPLEPIE_TYPE_RSS_090 RSS 0.90.
1668
	 * @see SIMPLEPIE_TYPE_RSS_091_NETSCAPE RSS 0.91 (Netscape).
1669
	 * @see SIMPLEPIE_TYPE_RSS_091_USERLAND RSS 0.91 (Userland).
1670
	 * @see SIMPLEPIE_TYPE_RSS_091 RSS 0.91.
1671
	 * @see SIMPLEPIE_TYPE_RSS_092 RSS 0.92.
1672
	 * @see SIMPLEPIE_TYPE_RSS_093 RSS 0.93.
1673
	 * @see SIMPLEPIE_TYPE_RSS_094 RSS 0.94.
1674
	 * @see SIMPLEPIE_TYPE_RSS_10 RSS 1.0.
1675
	 * @see SIMPLEPIE_TYPE_RSS_20 RSS 2.0.x.
1676
	 * @see SIMPLEPIE_TYPE_RSS_RDF RDF-based RSS.
1677
	 * @see SIMPLEPIE_TYPE_RSS_SYNDICATION Non-RDF-based RSS (truly intended as syndication format).
1678
	 * @see SIMPLEPIE_TYPE_RSS_ALL Any version of RSS.
1679
	 * @see SIMPLEPIE_TYPE_ATOM_03 Atom 0.3.
1680
	 * @see SIMPLEPIE_TYPE_ATOM_10 Atom 1.0.
1681
	 * @see SIMPLEPIE_TYPE_ATOM_ALL Any version of Atom.
1682
	 * @see SIMPLEPIE_TYPE_ALL Any known/supported feed type.
1683
	 * @return int SIMPLEPIE_TYPE_* constant
1684
	 */
1685
	public function get_type()
1686
	{
1687
		if (!isset($this->data['type']))
1688
		{
1689
			$this->data['type'] = SIMPLEPIE_TYPE_ALL;
1690
			if (isset($this->data['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['feed']))
1691
			{
1692
				$this->data['type'] &= SIMPLEPIE_TYPE_ATOM_10;
1693
			}
1694
			elseif (isset($this->data['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['feed']))
1695
			{
1696
				$this->data['type'] &= SIMPLEPIE_TYPE_ATOM_03;
1697
			}
1698
			elseif (isset($this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF']))
1699
			{
1700 View Code Duplication
				if (isset($this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]['child'][SIMPLEPIE_NAMESPACE_RSS_10]['channel'])
1701
				|| isset($this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]['child'][SIMPLEPIE_NAMESPACE_RSS_10]['image'])
1702
				|| isset($this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]['child'][SIMPLEPIE_NAMESPACE_RSS_10]['item'])
1703
				|| isset($this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]['child'][SIMPLEPIE_NAMESPACE_RSS_10]['textinput']))
1704
				{
1705
					$this->data['type'] &= SIMPLEPIE_TYPE_RSS_10;
1706
				}
1707 View Code Duplication
				if (isset($this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]['child'][SIMPLEPIE_NAMESPACE_RSS_090]['channel'])
1708
				|| isset($this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]['child'][SIMPLEPIE_NAMESPACE_RSS_090]['image'])
1709
				|| isset($this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]['child'][SIMPLEPIE_NAMESPACE_RSS_090]['item'])
1710
				|| isset($this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]['child'][SIMPLEPIE_NAMESPACE_RSS_090]['textinput']))
1711
				{
1712
					$this->data['type'] &= SIMPLEPIE_TYPE_RSS_090;
1713
				}
1714
			}
1715
			elseif (isset($this->data['child'][SIMPLEPIE_NAMESPACE_RSS_20]['rss']))
1716
			{
1717
				$this->data['type'] &= SIMPLEPIE_TYPE_RSS_ALL;
1718
				if (isset($this->data['child'][SIMPLEPIE_NAMESPACE_RSS_20]['rss'][0]['attribs']['']['version']))
1719
				{
1720
					switch (trim($this->data['child'][SIMPLEPIE_NAMESPACE_RSS_20]['rss'][0]['attribs']['']['version']))
1721
					{
1722
						case '0.91':
1723
							$this->data['type'] &= SIMPLEPIE_TYPE_RSS_091;
1724
							if (isset($this->data['child'][SIMPLEPIE_NAMESPACE_RSS_20]['rss'][0]['child'][SIMPLEPIE_NAMESPACE_RSS_20]['skiphours']['hour'][0]['data']))
1725
							{
1726
								switch (trim($this->data['child'][SIMPLEPIE_NAMESPACE_RSS_20]['rss'][0]['child'][SIMPLEPIE_NAMESPACE_RSS_20]['skiphours']['hour'][0]['data']))
1727
								{
1728
									case '0':
1729
										$this->data['type'] &= SIMPLEPIE_TYPE_RSS_091_NETSCAPE;
1730
										break;
1731
1732
									case '24':
1733
										$this->data['type'] &= SIMPLEPIE_TYPE_RSS_091_USERLAND;
1734
										break;
1735
								}
1736
							}
1737
							break;
1738
1739
						case '0.92':
1740
							$this->data['type'] &= SIMPLEPIE_TYPE_RSS_092;
1741
							break;
1742
1743
						case '0.93':
1744
							$this->data['type'] &= SIMPLEPIE_TYPE_RSS_093;
1745
							break;
1746
1747
						case '0.94':
1748
							$this->data['type'] &= SIMPLEPIE_TYPE_RSS_094;
1749
							break;
1750
1751
						case '2.0':
1752
							$this->data['type'] &= SIMPLEPIE_TYPE_RSS_20;
1753
							break;
1754
					}
1755
				}
1756
			}
1757
			else
1758
			{
1759
				$this->data['type'] = SIMPLEPIE_TYPE_NONE;
1760
			}
1761
		}
1762
		return $this->data['type'];
1763
	}
1764
1765
	/**
1766
	 * Get the URL for the feed
1767
	 *
1768
	 * May or may not be different from the URL passed to {@see set_feed_url()},
1769
	 * depending on whether auto-discovery was used.
1770
	 *
1771
	 * @since Preview Release (previously called `get_feed_url()` since SimplePie 0.8.)
1772
	 * @todo If we have a perm redirect we should return the new URL
1773
	 * @todo When we make the above change, let's support <itunes:new-feed-url> as well
1774
	 * @todo Also, |atom:link|@rel=self
1775
	 * @return string|null
1776
	 */
1777
	public function subscribe_url()
1778
	{
1779
		if ($this->feed_url !== null)
1780
		{
1781
			return $this->sanitize($this->feed_url, SIMPLEPIE_CONSTRUCT_IRI);
1782
		}
1783
		else
1784
		{
1785
			return null;
1786
		}
1787
	}
1788
1789
	/**
1790
	 * Get data for an feed-level element
1791
	 *
1792
	 * This method allows you to get access to ANY element/attribute that is a
1793
	 * sub-element of the opening feed tag.
1794
	 *
1795
	 * The return value is an indexed array of elements matching the given
1796
	 * namespace and tag name. Each element has `attribs`, `data` and `child`
1797
	 * subkeys. For `attribs` and `child`, these contain namespace subkeys.
1798
	 * `attribs` then has one level of associative name => value data (where
1799
	 * `value` is a string) after the namespace. `child` has tag-indexed keys
1800
	 * after the namespace, each member of which is an indexed array matching
1801
	 * this same format.
1802
	 *
1803
	 * For example:
1804
	 * <pre>
1805
	 * // This is probably a bad example because we already support
1806
	 * // <media:content> natively, but it shows you how to parse through
1807
	 * // the nodes.
1808
	 * $group = $item->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'group');
1809
	 * $content = $group[0]['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['content'];
1810
	 * $file = $content[0]['attribs']['']['url'];
1811
	 * echo $file;
1812
	 * </pre>
1813
	 *
1814
	 * @since 1.0
1815
	 * @see http://simplepie.org/wiki/faq/supported_xml_namespaces
1816
	 * @param string $namespace The URL of the XML namespace of the elements you're trying to access
1817
	 * @param string $tag Tag name
1818
	 * @return array
1819
	 */
1820
	public function get_feed_tags($namespace, $tag)
1821
	{
1822
		$type = $this->get_type();
1823 View Code Duplication
		if ($type & SIMPLEPIE_TYPE_ATOM_10)
1824
		{
1825
			if (isset($this->data['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['feed'][0]['child'][$namespace][$tag]))
1826
			{
1827
				return $this->data['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['feed'][0]['child'][$namespace][$tag];
1828
			}
1829
		}
1830 View Code Duplication
		if ($type & SIMPLEPIE_TYPE_ATOM_03)
1831
		{
1832
			if (isset($this->data['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['feed'][0]['child'][$namespace][$tag]))
1833
			{
1834
				return $this->data['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['feed'][0]['child'][$namespace][$tag];
1835
			}
1836
		}
1837 View Code Duplication
		if ($type & SIMPLEPIE_TYPE_RSS_RDF)
1838
		{
1839
			if (isset($this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]['child'][$namespace][$tag]))
1840
			{
1841
				return $this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]['child'][$namespace][$tag];
1842
			}
1843
		}
1844 View Code Duplication
		if ($type & SIMPLEPIE_TYPE_RSS_SYNDICATION)
1845
		{
1846
			if (isset($this->data['child'][SIMPLEPIE_NAMESPACE_RSS_20]['rss'][0]['child'][$namespace][$tag]))
1847
			{
1848
				return $this->data['child'][SIMPLEPIE_NAMESPACE_RSS_20]['rss'][0]['child'][$namespace][$tag];
1849
			}
1850
		}
1851
		return null;
1852
	}
1853
1854
	/**
1855
	 * Get data for an channel-level element
1856
	 *
1857
	 * This method allows you to get access to ANY element/attribute in the
1858
	 * channel/header section of the feed.
1859
	 *
1860
	 * See {@see SimplePie::get_feed_tags()} for a description of the return value
1861
	 *
1862
	 * @since 1.0
1863
	 * @see http://simplepie.org/wiki/faq/supported_xml_namespaces
1864
	 * @param string $namespace The URL of the XML namespace of the elements you're trying to access
1865
	 * @param string $tag Tag name
1866
	 * @return array
1867
	 */
1868
	public function get_channel_tags($namespace, $tag)
1869
	{
1870
		$type = $this->get_type();
1871
		if ($type & SIMPLEPIE_TYPE_ATOM_ALL)
1872
		{
1873
			if ($return = $this->get_feed_tags($namespace, $tag))
1874
			{
1875
				return $return;
1876
			}
1877
		}
1878
		if ($type & SIMPLEPIE_TYPE_RSS_10)
1879
		{
1880
			if ($channel = $this->get_feed_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'channel'))
1881
			{
1882
				if (isset($channel[0]['child'][$namespace][$tag]))
1883
				{
1884
					return $channel[0]['child'][$namespace][$tag];
1885
				}
1886
			}
1887
		}
1888
		if ($type & SIMPLEPIE_TYPE_RSS_090)
1889
		{
1890
			if ($channel = $this->get_feed_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'channel'))
1891
			{
1892
				if (isset($channel[0]['child'][$namespace][$tag]))
1893
				{
1894
					return $channel[0]['child'][$namespace][$tag];
1895
				}
1896
			}
1897
		}
1898 View Code Duplication
		if ($type & SIMPLEPIE_TYPE_RSS_SYNDICATION)
1899
		{
1900
			if ($channel = $this->get_feed_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'channel'))
1901
			{
1902
				if (isset($channel[0]['child'][$namespace][$tag]))
1903
				{
1904
					return $channel[0]['child'][$namespace][$tag];
1905
				}
1906
			}
1907
		}
1908
		return null;
1909
	}
1910
1911
	/**
1912
	 * Get data for an channel-level element
1913
	 *
1914
	 * This method allows you to get access to ANY element/attribute in the
1915
	 * image/logo section of the feed.
1916
	 *
1917
	 * See {@see SimplePie::get_feed_tags()} for a description of the return value
1918
	 *
1919
	 * @since 1.0
1920
	 * @see http://simplepie.org/wiki/faq/supported_xml_namespaces
1921
	 * @param string $namespace The URL of the XML namespace of the elements you're trying to access
1922
	 * @param string $tag Tag name
1923
	 * @return array
1924
	 */
1925
	public function get_image_tags($namespace, $tag)
1926
	{
1927
		$type = $this->get_type();
1928 View Code Duplication
		if ($type & SIMPLEPIE_TYPE_RSS_10)
1929
		{
1930
			if ($image = $this->get_feed_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'image'))
1931
			{
1932
				if (isset($image[0]['child'][$namespace][$tag]))
1933
				{
1934
					return $image[0]['child'][$namespace][$tag];
1935
				}
1936
			}
1937
		}
1938 View Code Duplication
		if ($type & SIMPLEPIE_TYPE_RSS_090)
1939
		{
1940
			if ($image = $this->get_feed_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'image'))
1941
			{
1942
				if (isset($image[0]['child'][$namespace][$tag]))
1943
				{
1944
					return $image[0]['child'][$namespace][$tag];
1945
				}
1946
			}
1947
		}
1948 View Code Duplication
		if ($type & SIMPLEPIE_TYPE_RSS_SYNDICATION)
1949
		{
1950
			if ($image = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'image'))
1951
			{
1952
				if (isset($image[0]['child'][$namespace][$tag]))
1953
				{
1954
					return $image[0]['child'][$namespace][$tag];
1955
				}
1956
			}
1957
		}
1958
		return null;
1959
	}
1960
1961
	/**
1962
	 * Get the base URL value from the feed
1963
	 *
1964
	 * Uses `<xml:base>` if available, otherwise uses the first link in the
1965
	 * feed, or failing that, the URL of the feed itself.
1966
	 *
1967
	 * @see get_link
1968
	 * @see subscribe_url
1969
	 *
1970
	 * @param array $element
1971
	 * @return string
1972
	 */
1973
	public function get_base($element = array())
1974
	{
1975
		if (!($this->get_type() & SIMPLEPIE_TYPE_RSS_SYNDICATION) && !empty($element['xml_base_explicit']) && isset($element['xml_base']))
1976
		{
1977
			return $element['xml_base'];
1978
		}
1979
		elseif ($this->get_link() !== null)
1980
		{
1981
			return $this->get_link();
1982
		}
1983
		else
1984
		{
1985
			return $this->subscribe_url();
1986
		}
1987
	}
1988
1989
	/**
1990
	 * Sanitize feed data
1991
	 *
1992
	 * @access private
1993
	 * @see SimplePie_Sanitize::sanitize()
1994
	 * @param string $data Data to sanitize
1995
	 * @param int $type One of the SIMPLEPIE_CONSTRUCT_* constants
1996
	 * @param string $base Base URL to resolve URLs against
1997
	 * @return string Sanitized data
1998
	 */
1999
	public function sanitize($data, $type, $base = '')
2000
	{
2001
		return $this->sanitize->sanitize($data, $type, $base);
2002
	}
2003
2004
	/**
2005
	 * Get the title of the feed
2006
	 *
2007
	 * Uses `<atom:title>`, `<title>` or `<dc:title>`
2008
	 *
2009
	 * @since 1.0 (previously called `get_feed_title` since 0.8)
2010
	 * @return string|null
2011
	 */
2012 View Code Duplication
	public function get_title()
2013
	{
2014
		if ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'title'))
2015
		{
2016
			return $this->sanitize($return[0]['data'], $this->registry->call('Misc', 'atom_10_construct_type', array($return[0]['attribs'])), $this->get_base($return[0]));
2017
		}
2018
		elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'title'))
2019
		{
2020
			return $this->sanitize($return[0]['data'], $this->registry->call('Misc', 'atom_03_construct_type', array($return[0]['attribs'])), $this->get_base($return[0]));
2021
		}
2022
		elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'title'))
2023
		{
2024
			return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
2025
		}
2026
		elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'title'))
2027
		{
2028
			return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
2029
		}
2030
		elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'title'))
2031
		{
2032
			return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
2033
		}
2034
		elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_11, 'title'))
2035
		{
2036
			return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2037
		}
2038
		elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_10, 'title'))
2039
		{
2040
			return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2041
		}
2042
		else
2043
		{
2044
			return null;
2045
		}
2046
	}
2047
2048
	/**
2049
	 * Get a category for the feed
2050
	 *
2051
	 * @since Unknown
2052
	 * @param int $key The category that you want to return.  Remember that arrays begin with 0, not 1
2053
	 * @return SimplePie_Category|null
2054
	 */
2055 View Code Duplication
	public function get_category($key = 0)
2056
	{
2057
		$categories = $this->get_categories();
2058
		if (isset($categories[$key]))
2059
		{
2060
			return $categories[$key];
2061
		}
2062
		else
2063
		{
2064
			return null;
2065
		}
2066
	}
2067
2068
	/**
2069
	 * Get all categories for the feed
2070
	 *
2071
	 * Uses `<atom:category>`, `<category>` or `<dc:subject>`
2072
	 *
2073
	 * @since Unknown
2074
	 * @return array|null List of {@see SimplePie_Category} objects
2075
	 */
2076 View Code Duplication
	public function get_categories()
2077
	{
2078
		$categories = array();
2079
2080
		foreach ((array) $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'category') as $category)
2081
		{
2082
			$term = null;
2083
			$scheme = null;
2084
			$label = null;
2085
			if (isset($category['attribs']['']['term']))
2086
			{
2087
				$term = $this->sanitize($category['attribs']['']['term'], SIMPLEPIE_CONSTRUCT_TEXT);
2088
			}
2089
			if (isset($category['attribs']['']['scheme']))
2090
			{
2091
				$scheme = $this->sanitize($category['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
2092
			}
2093
			if (isset($category['attribs']['']['label']))
2094
			{
2095
				$label = $this->sanitize($category['attribs']['']['label'], SIMPLEPIE_CONSTRUCT_TEXT);
2096
			}
2097
			$categories[] = $this->registry->create('Category', array($term, $scheme, $label));
2098
		}
2099
		foreach ((array) $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'category') as $category)
2100
		{
2101
			// This is really the label, but keep this as the term also for BC.
2102
			// Label will also work on retrieving because that falls back to term.
2103
			$term = $this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2104
			if (isset($category['attribs']['']['domain']))
2105
			{
2106
				$scheme = $this->sanitize($category['attribs']['']['domain'], SIMPLEPIE_CONSTRUCT_TEXT);
2107
			}
2108
			else
2109
			{
2110
				$scheme = null;
2111
			}
2112
			$categories[] = $this->registry->create('Category', array($term, $scheme, null));
2113
		}
2114
		foreach ((array) $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_11, 'subject') as $category)
2115
		{
2116
			$categories[] = $this->registry->create('Category', array($this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null));
2117
		}
2118
		foreach ((array) $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_10, 'subject') as $category)
2119
		{
2120
			$categories[] = $this->registry->create('Category', array($this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null));
2121
		}
2122
2123
		if (!empty($categories))
2124
		{
2125
			return array_unique($categories);
2126
		}
2127
		else
2128
		{
2129
			return null;
2130
		}
2131
	}
2132
2133
	/**
2134
	 * Get an author for the feed
2135
	 *
2136
	 * @since 1.1
2137
	 * @param int $key The author that you want to return.  Remember that arrays begin with 0, not 1
2138
	 * @return SimplePie_Author|null
2139
	 */
2140 View Code Duplication
	public function get_author($key = 0)
2141
	{
2142
		$authors = $this->get_authors();
2143
		if (isset($authors[$key]))
2144
		{
2145
			return $authors[$key];
2146
		}
2147
		else
2148
		{
2149
			return null;
2150
		}
2151
	}
2152
2153
	/**
2154
	 * Get all authors for the feed
2155
	 *
2156
	 * Uses `<atom:author>`, `<author>`, `<dc:creator>` or `<itunes:author>`
2157
	 *
2158
	 * @since 1.1
2159
	 * @return array|null List of {@see SimplePie_Author} objects
2160
	 */
2161 View Code Duplication
	public function get_authors()
2162
	{
2163
		$authors = array();
2164
		foreach ((array) $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'author') as $author)
2165
		{
2166
			$name = null;
2167
			$uri = null;
2168
			$email = null;
2169
			if (isset($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data']))
2170
			{
2171
				$name = $this->sanitize($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2172
			}
2173
			if (isset($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['uri'][0]['data']))
2174
			{
2175
				$uri = $this->sanitize($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['uri'][0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['uri'][0]));
2176
			}
2177
			if (isset($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data']))
2178
			{
2179
				$email = $this->sanitize($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2180
			}
2181
			if ($name !== null || $email !== null || $uri !== null)
2182
			{
2183
				$authors[] = $this->registry->create('Author', array($name, $uri, $email));
2184
			}
2185
		}
2186
		if ($author = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'author'))
2187
		{
2188
			$name = null;
2189
			$url = null;
2190
			$email = null;
2191
			if (isset($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data']))
2192
			{
2193
				$name = $this->sanitize($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2194
			}
2195
			if (isset($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['url'][0]['data']))
2196
			{
2197
				$url = $this->sanitize($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['url'][0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['url'][0]));
2198
			}
2199
			if (isset($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data']))
2200
			{
2201
				$email = $this->sanitize($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2202
			}
2203
			if ($name !== null || $email !== null || $url !== null)
2204
			{
2205
				$authors[] = $this->registry->create('Author', array($name, $url, $email));
2206
			}
2207
		}
2208
		foreach ((array) $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_11, 'creator') as $author)
2209
		{
2210
			$authors[] = $this->registry->create('Author', array($this->sanitize($author['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null));
2211
		}
2212
		foreach ((array) $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_10, 'creator') as $author)
2213
		{
2214
			$authors[] = $this->registry->create('Author', array($this->sanitize($author['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null));
2215
		}
2216
		foreach ((array) $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'author') as $author)
2217
		{
2218
			$authors[] = $this->registry->create('Author', array($this->sanitize($author['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null));
2219
		}
2220
2221
		if (!empty($authors))
2222
		{
2223
			return array_unique($authors);
2224
		}
2225
		else
2226
		{
2227
			return null;
2228
		}
2229
	}
2230
2231
	/**
2232
	 * Get a contributor for the feed
2233
	 *
2234
	 * @since 1.1
2235
	 * @param int $key The contrbutor that you want to return.  Remember that arrays begin with 0, not 1
2236
	 * @return SimplePie_Author|null
2237
	 */
2238 View Code Duplication
	public function get_contributor($key = 0)
2239
	{
2240
		$contributors = $this->get_contributors();
2241
		if (isset($contributors[$key]))
2242
		{
2243
			return $contributors[$key];
2244
		}
2245
		else
2246
		{
2247
			return null;
2248
		}
2249
	}
2250
2251
	/**
2252
	 * Get all contributors for the feed
2253
	 *
2254
	 * Uses `<atom:contributor>`
2255
	 *
2256
	 * @since 1.1
2257
	 * @return array|null List of {@see SimplePie_Author} objects
2258
	 */
2259 View Code Duplication
	public function get_contributors()
2260
	{
2261
		$contributors = array();
2262
		foreach ((array) $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'contributor') as $contributor)
2263
		{
2264
			$name = null;
2265
			$uri = null;
2266
			$email = null;
2267
			if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data']))
2268
			{
2269
				$name = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2270
			}
2271
			if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['uri'][0]['data']))
2272
			{
2273
				$uri = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['uri'][0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['uri'][0]));
2274
			}
2275
			if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data']))
2276
			{
2277
				$email = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2278
			}
2279
			if ($name !== null || $email !== null || $uri !== null)
2280
			{
2281
				$contributors[] = $this->registry->create('Author', array($name, $uri, $email));
2282
			}
2283
		}
2284
		foreach ((array) $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'contributor') as $contributor)
2285
		{
2286
			$name = null;
2287
			$url = null;
2288
			$email = null;
2289
			if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data']))
2290
			{
2291
				$name = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2292
			}
2293
			if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['url'][0]['data']))
2294
			{
2295
				$url = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['url'][0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['url'][0]));
2296
			}
2297
			if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data']))
2298
			{
2299
				$email = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2300
			}
2301
			if ($name !== null || $email !== null || $url !== null)
2302
			{
2303
				$contributors[] = $this->registry->create('Author', array($name, $url, $email));
2304
			}
2305
		}
2306
2307
		if (!empty($contributors))
2308
		{
2309
			return array_unique($contributors);
2310
		}
2311
		else
2312
		{
2313
			return null;
2314
		}
2315
	}
2316
2317
	/**
2318
	 * Get a single link for the feed
2319
	 *
2320
	 * @since 1.0 (previously called `get_feed_link` since Preview Release, `get_feed_permalink()` since 0.8)
2321
	 * @param int $key The link that you want to return.  Remember that arrays begin with 0, not 1
2322
	 * @param string $rel The relationship of the link to return
2323
	 * @return string|null Link URL
2324
	 */
2325 View Code Duplication
	public function get_link($key = 0, $rel = 'alternate')
2326
	{
2327
		$links = $this->get_links($rel);
2328
		if (isset($links[$key]))
2329
		{
2330
			return $links[$key];
2331
		}
2332
		else
2333
		{
2334
			return null;
2335
		}
2336
	}
2337
2338
	/**
2339
	 * Get the permalink for the item
2340
	 *
2341
	 * Returns the first link available with a relationship of "alternate".
2342
	 * Identical to {@see get_link()} with key 0
2343
	 *
2344
	 * @see get_link
2345
	 * @since 1.0 (previously called `get_feed_link` since Preview Release, `get_feed_permalink()` since 0.8)
2346
	 * @internal Added for parity between the parent-level and the item/entry-level.
2347
	 * @return string|null Link URL
2348
	 */
2349
	public function get_permalink()
2350
	{
2351
		return $this->get_link(0);
2352
	}
2353
2354
	/**
2355
	 * Get all links for the feed
2356
	 *
2357
	 * Uses `<atom:link>` or `<link>`
2358
	 *
2359
	 * @since Beta 2
2360
	 * @param string $rel The relationship of links to return
2361
	 * @return array|null Links found for the feed (strings)
2362
	 */
2363 View Code Duplication
	public function get_links($rel = 'alternate')
2364
	{
2365
		if (!isset($this->data['links']))
2366
		{
2367
			$this->data['links'] = array();
2368
			if ($links = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'link'))
2369
			{
2370
				foreach ($links as $link)
2371
				{
2372
					if (isset($link['attribs']['']['href']))
2373
					{
2374
						$link_rel = (isset($link['attribs']['']['rel'])) ? $link['attribs']['']['rel'] : 'alternate';
2375
						$this->data['links'][$link_rel][] = $this->sanitize($link['attribs']['']['href'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($link));
2376
					}
2377
				}
2378
			}
2379
			if ($links = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'link'))
2380
			{
2381
				foreach ($links as $link)
2382
				{
2383
					if (isset($link['attribs']['']['href']))
2384
					{
2385
						$link_rel = (isset($link['attribs']['']['rel'])) ? $link['attribs']['']['rel'] : 'alternate';
2386
						$this->data['links'][$link_rel][] = $this->sanitize($link['attribs']['']['href'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($link));
2387
2388
					}
2389
				}
2390
			}
2391
			if ($links = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'link'))
2392
			{
2393
				$this->data['links']['alternate'][] = $this->sanitize($links[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($links[0]));
2394
			}
2395
			if ($links = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'link'))
2396
			{
2397
				$this->data['links']['alternate'][] = $this->sanitize($links[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($links[0]));
2398
			}
2399
			if ($links = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'link'))
2400
			{
2401
				$this->data['links']['alternate'][] = $this->sanitize($links[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($links[0]));
2402
			}
2403
2404
			$keys = array_keys($this->data['links']);
2405
			foreach ($keys as $key)
2406
			{
2407
				if ($this->registry->call('Misc', 'is_isegment_nz_nc', array($key)))
2408
				{
2409
					if (isset($this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key]))
2410
					{
2411
						$this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key] = array_merge($this->data['links'][$key], $this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key]);
2412
						$this->data['links'][$key] =& $this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key];
2413
					}
2414
					else
2415
					{
2416
						$this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key] =& $this->data['links'][$key];
2417
					}
2418
				}
2419
				elseif (substr($key, 0, 41) === SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY)
2420
				{
2421
					$this->data['links'][substr($key, 41)] =& $this->data['links'][$key];
2422
				}
2423
				$this->data['links'][$key] = array_unique($this->data['links'][$key]);
2424
			}
2425
		}
2426
2427
		if (isset($this->data['links'][$rel]))
2428
		{
2429
			return $this->data['links'][$rel];
2430
		}
2431
		else
2432
		{
2433
			return null;
2434
		}
2435
	}
2436
2437
	public function get_all_discovered_feeds()
2438
	{
2439
		return $this->all_discovered_feeds;
2440
	}
2441
2442
	/**
2443
	 * Get the content for the item
2444
	 *
2445
	 * Uses `<atom:subtitle>`, `<atom:tagline>`, `<description>`,
2446
	 * `<dc:description>`, `<itunes:summary>` or `<itunes:subtitle>`
2447
	 *
2448
	 * @since 1.0 (previously called `get_feed_description()` since 0.8)
2449
	 * @return string|null
2450
	 */
2451 View Code Duplication
	public function get_description()
2452
	{
2453
		if ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'subtitle'))
2454
		{
2455
			return $this->sanitize($return[0]['data'], $this->registry->call('Misc', 'atom_10_construct_type', array($return[0]['attribs'])), $this->get_base($return[0]));
2456
		}
2457
		elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'tagline'))
2458
		{
2459
			return $this->sanitize($return[0]['data'], $this->registry->call('Misc', 'atom_03_construct_type', array($return[0]['attribs'])), $this->get_base($return[0]));
2460
		}
2461
		elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'description'))
2462
		{
2463
			return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
2464
		}
2465
		elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'description'))
2466
		{
2467
			return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
2468
		}
2469
		elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'description'))
2470
		{
2471
			return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_HTML, $this->get_base($return[0]));
2472
		}
2473
		elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_11, 'description'))
2474
		{
2475
			return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2476
		}
2477
		elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_10, 'description'))
2478
		{
2479
			return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2480
		}
2481
		elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'summary'))
2482
		{
2483
			return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_HTML, $this->get_base($return[0]));
2484
		}
2485
		elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'subtitle'))
2486
		{
2487
			return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_HTML, $this->get_base($return[0]));
2488
		}
2489
		else
2490
		{
2491
			return null;
2492
		}
2493
	}
2494
2495
	/**
2496
	 * Get the copyright info for the feed
2497
	 *
2498
	 * Uses `<atom:rights>`, `<atom:copyright>` or `<dc:rights>`
2499
	 *
2500
	 * @since 1.0 (previously called `get_feed_copyright()` since 0.8)
2501
	 * @return string|null
2502
	 */
2503 View Code Duplication
	public function get_copyright()
2504
	{
2505
		if ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'rights'))
2506
		{
2507
			return $this->sanitize($return[0]['data'], $this->registry->call('Misc', 'atom_10_construct_type', array($return[0]['attribs'])), $this->get_base($return[0]));
2508
		}
2509
		elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'copyright'))
2510
		{
2511
			return $this->sanitize($return[0]['data'], $this->registry->call('Misc', 'atom_03_construct_type', array($return[0]['attribs'])), $this->get_base($return[0]));
2512
		}
2513
		elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'copyright'))
2514
		{
2515
			return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2516
		}
2517
		elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_11, 'rights'))
2518
		{
2519
			return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2520
		}
2521
		elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_10, 'rights'))
2522
		{
2523
			return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2524
		}
2525
		else
2526
		{
2527
			return null;
2528
		}
2529
	}
2530
2531
	/**
2532
	 * Get the language for the feed
2533
	 *
2534
	 * Uses `<language>`, `<dc:language>`, or @xml_lang
2535
	 *
2536
	 * @since 1.0 (previously called `get_feed_language()` since 0.8)
2537
	 * @return string|null
2538
	 */
2539
	public function get_language()
2540
	{
2541
		if ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'language'))
2542
		{
2543
			return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2544
		}
2545
		elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_11, 'language'))
2546
		{
2547
			return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2548
		}
2549
		elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_10, 'language'))
2550
		{
2551
			return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2552
		}
2553 View Code Duplication
		elseif (isset($this->data['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['feed'][0]['xml_lang']))
2554
		{
2555
			return $this->sanitize($this->data['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['feed'][0]['xml_lang'], SIMPLEPIE_CONSTRUCT_TEXT);
2556
		}
2557 View Code Duplication
		elseif (isset($this->data['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['feed'][0]['xml_lang']))
2558
		{
2559
			return $this->sanitize($this->data['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['feed'][0]['xml_lang'], SIMPLEPIE_CONSTRUCT_TEXT);
2560
		}
2561 View Code Duplication
		elseif (isset($this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]['xml_lang']))
2562
		{
2563
			return $this->sanitize($this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]['xml_lang'], SIMPLEPIE_CONSTRUCT_TEXT);
2564
		}
2565
		elseif (isset($this->data['headers']['content-language']))
2566
		{
2567
			return $this->sanitize($this->data['headers']['content-language'], SIMPLEPIE_CONSTRUCT_TEXT);
2568
		}
2569
		else
2570
		{
2571
			return null;
2572
		}
2573
	}
2574
2575
	/**
2576
	 * Get the latitude coordinates for the item
2577
	 *
2578
	 * Compatible with the W3C WGS84 Basic Geo and GeoRSS specifications
2579
	 *
2580
	 * Uses `<geo:lat>` or `<georss:point>`
2581
	 *
2582
	 * @since 1.0
2583
	 * @link http://www.w3.org/2003/01/geo/ W3C WGS84 Basic Geo
2584
	 * @link http://www.georss.org/ GeoRSS
2585
	 * @return string|null
0 ignored issues
show
Should the return type not be double|null?

This check compares the return type specified in the @return annotation of a function or method doc comment with the types returned by the function and raises an issue if they mismatch.

Loading history...
2586
	 */
2587 View Code Duplication
	public function get_latitude()
2588
	{
2589
2590
		if ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_W3C_BASIC_GEO, 'lat'))
2591
		{
2592
			return (float) $return[0]['data'];
2593
		}
2594
		elseif (($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_GEORSS, 'point')) && preg_match('/^((?:-)?[0-9]+(?:\.[0-9]+)) ((?:-)?[0-9]+(?:\.[0-9]+))$/', trim($return[0]['data']), $match))
2595
		{
2596
			return (float) $match[1];
2597
		}
2598
		else
2599
		{
2600
			return null;
2601
		}
2602
	}
2603
2604
	/**
2605
	 * Get the longitude coordinates for the feed
2606
	 *
2607
	 * Compatible with the W3C WGS84 Basic Geo and GeoRSS specifications
2608
	 *
2609
	 * Uses `<geo:long>`, `<geo:lon>` or `<georss:point>`
2610
	 *
2611
	 * @since 1.0
2612
	 * @link http://www.w3.org/2003/01/geo/ W3C WGS84 Basic Geo
2613
	 * @link http://www.georss.org/ GeoRSS
2614
	 * @return string|null
0 ignored issues
show
Should the return type not be double|null?

This check compares the return type specified in the @return annotation of a function or method doc comment with the types returned by the function and raises an issue if they mismatch.

Loading history...
2615
	 */
2616 View Code Duplication
	public function get_longitude()
2617
	{
2618
		if ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_W3C_BASIC_GEO, 'long'))
2619
		{
2620
			return (float) $return[0]['data'];
2621
		}
2622
		elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_W3C_BASIC_GEO, 'lon'))
2623
		{
2624
			return (float) $return[0]['data'];
2625
		}
2626
		elseif (($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_GEORSS, 'point')) && preg_match('/^((?:-)?[0-9]+(?:\.[0-9]+)) ((?:-)?[0-9]+(?:\.[0-9]+))$/', trim($return[0]['data']), $match))
2627
		{
2628
			return (float) $match[2];
2629
		}
2630
		else
2631
		{
2632
			return null;
2633
		}
2634
	}
2635
2636
	/**
2637
	 * Get the feed logo's title
2638
	 *
2639
	 * RSS 0.9.0, 1.0 and 2.0 feeds are allowed to have a "feed logo" title.
2640
	 *
2641
	 * Uses `<image><title>` or `<image><dc:title>`
2642
	 *
2643
	 * @return string|null
2644
	 */
2645
	public function get_image_title()
2646
	{
2647
		if ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'title'))
2648
		{
2649
			return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2650
		}
2651 View Code Duplication
		elseif ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'title'))
2652
		{
2653
			return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2654
		}
2655 View Code Duplication
		elseif ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'title'))
2656
		{
2657
			return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2658
		}
2659 View Code Duplication
		elseif ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_DC_11, 'title'))
2660
		{
2661
			return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2662
		}
2663 View Code Duplication
		elseif ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_DC_10, 'title'))
2664
		{
2665
			return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
2666
		}
2667
		else
2668
		{
2669
			return null;
2670
		}
2671
	}
2672
2673
	/**
2674
	 * Get the feed logo's URL
2675
	 *
2676
	 * RSS 0.9.0, 2.0, Atom 1.0, and feeds with iTunes RSS tags are allowed to
2677
	 * have a "feed logo" URL. This points directly to the image itself.
2678
	 *
2679
	 * Uses `<itunes:image>`, `<atom:logo>`, `<atom:icon>`,
2680
	 * `<image><title>` or `<image><dc:title>`
2681
	 *
2682
	 * @return string|null
2683
	 */
2684
	public function get_image_url()
2685
	{
2686
		if ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'image'))
2687
		{
2688
			return $this->sanitize($return[0]['attribs']['']['href'], SIMPLEPIE_CONSTRUCT_IRI);
2689
		}
2690
		elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'logo'))
2691
		{
2692
			return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($return[0]));
2693
		}
2694
		elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'icon'))
2695
		{
2696
			return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($return[0]));
2697
		}
2698
		elseif ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'url'))
2699
		{
2700
			return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($return[0]));
2701
		}
2702
		elseif ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'url'))
2703
		{
2704
			return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($return[0]));
2705
		}
2706
		elseif ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'url'))
2707
		{
2708
			return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($return[0]));
2709
		}
2710
		else
2711
		{
2712
			return null;
2713
		}
2714
	}
2715
2716
2717
	/**
2718
	 * Get the feed logo's link
2719
	 *
2720
	 * RSS 0.9.0, 1.0 and 2.0 feeds are allowed to have a "feed logo" link. This
2721
	 * points to a human-readable page that the image should link to.
2722
	 *
2723
	 * Uses `<itunes:image>`, `<atom:logo>`, `<atom:icon>`,
2724
	 * `<image><title>` or `<image><dc:title>`
2725
	 *
2726
	 * @return string|null
2727
	 */
2728 View Code Duplication
	public function get_image_link()
2729
	{
2730
		if ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'link'))
2731
		{
2732
			return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($return[0]));
2733
		}
2734
		elseif ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'link'))
2735
		{
2736
			return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($return[0]));
2737
		}
2738
		elseif ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'link'))
2739
		{
2740
			return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($return[0]));
2741
		}
2742
		else
2743
		{
2744
			return null;
2745
		}
2746
	}
2747
2748
	/**
2749
	 * Get the feed logo's link
2750
	 *
2751
	 * RSS 2.0 feeds are allowed to have a "feed logo" width.
2752
	 *
2753
	 * Uses `<image><width>` or defaults to 88.0 if no width is specified and
2754
	 * the feed is an RSS 2.0 feed.
2755
	 *
2756
	 * @return int|float|null
0 ignored issues
show
Consider making the return type a bit more specific; maybe use double|null.

This check looks for the generic type array as a return type and suggests a more specific type. This type is inferred from the actual code.

Loading history...
2757
	 */
2758 View Code Duplication
	public function get_image_width()
2759
	{
2760
		if ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'width'))
2761
		{
2762
			return round($return[0]['data']);
2763
		}
2764
		elseif ($this->get_type() & SIMPLEPIE_TYPE_RSS_SYNDICATION && $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'url'))
2765
		{
2766
			return 88.0;
2767
		}
2768
		else
2769
		{
2770
			return null;
2771
		}
2772
	}
2773
2774
	/**
2775
	 * Get the feed logo's height
2776
	 *
2777
	 * RSS 2.0 feeds are allowed to have a "feed logo" height.
2778
	 *
2779
	 * Uses `<image><height>` or defaults to 31.0 if no height is specified and
2780
	 * the feed is an RSS 2.0 feed.
2781
	 *
2782
	 * @return int|float|null
0 ignored issues
show
Consider making the return type a bit more specific; maybe use double|null.

This check looks for the generic type array as a return type and suggests a more specific type. This type is inferred from the actual code.

Loading history...
2783
	 */
2784 View Code Duplication
	public function get_image_height()
2785
	{
2786
		if ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'height'))
2787
		{
2788
			return round($return[0]['data']);
2789
		}
2790
		elseif ($this->get_type() & SIMPLEPIE_TYPE_RSS_SYNDICATION && $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'url'))
2791
		{
2792
			return 31.0;
2793
		}
2794
		else
2795
		{
2796
			return null;
2797
		}
2798
	}
2799
2800
	/**
2801
	 * Get the number of items in the feed
2802
	 *
2803
	 * This is well-suited for {@link http://php.net/for for()} loops with
2804
	 * {@see get_item()}
2805
	 *
2806
	 * @param int $max Maximum value to return. 0 for no limit
2807
	 * @return int Number of items in the feed
2808
	 */
2809
	public function get_item_quantity($max = 0)
2810
	{
2811
		$max = (int) $max;
2812
		$qty = count($this->get_items());
2813
		if ($max === 0)
2814
		{
2815
			return $qty;
2816
		}
2817
		else
2818
		{
2819
			return ($qty > $max) ? $max : $qty;
2820
		}
2821
	}
2822
2823
	/**
2824
	 * Get a single item from the feed
2825
	 *
2826
	 * This is better suited for {@link http://php.net/for for()} loops, whereas
2827
	 * {@see get_items()} is better suited for
2828
	 * {@link http://php.net/foreach foreach()} loops.
2829
	 *
2830
	 * @see get_item_quantity()
2831
	 * @since Beta 2
2832
	 * @param int $key The item that you want to return.  Remember that arrays begin with 0, not 1
2833
	 * @return SimplePie_Item|null
2834
	 */
2835
	public function get_item($key = 0)
2836
	{
2837
		$items = $this->get_items();
2838
		if (isset($items[$key]))
2839
		{
2840
			return $items[$key];
2841
		}
2842
		else
2843
		{
2844
			return null;
2845
		}
2846
	}
2847
2848
	/**
2849
	 * Get all items from the feed
2850
	 *
2851
	 * This is better suited for {@link http://php.net/for for()} loops, whereas
2852
	 * {@see get_items()} is better suited for
2853
	 * {@link http://php.net/foreach foreach()} loops.
2854
	 *
2855
	 * @see get_item_quantity
2856
	 * @since Beta 2
2857
	 * @param int $start Index to start at
2858
	 * @param int $end Number of items to return. 0 for all items after `$start`
2859
	 * @return array|null List of {@see SimplePie_Item} objects
2860
	 */
2861
	public function get_items($start = 0, $end = 0)
2862
	{
2863
		if (!isset($this->data['items']))
2864
		{
2865
			if (!empty($this->multifeed_objects))
2866
			{
2867
				$this->data['items'] = SimplePie::merge_items($this->multifeed_objects, $start, $end, $this->item_limit);
2868
			}
2869
			else
2870
			{
2871
				$this->data['items'] = array();
2872 View Code Duplication
				if ($items = $this->get_feed_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'entry'))
2873
				{
2874
					$keys = array_keys($items);
2875
					foreach ($keys as $key)
2876
					{
2877
						$this->data['items'][] = $this->registry->create('Item', array($this, $items[$key]));
2878
					}
2879
				}
2880 View Code Duplication
				if ($items = $this->get_feed_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'entry'))
2881
				{
2882
					$keys = array_keys($items);
2883
					foreach ($keys as $key)
2884
					{
2885
						$this->data['items'][] = $this->registry->create('Item', array($this, $items[$key]));
2886
					}
2887
				}
2888 View Code Duplication
				if ($items = $this->get_feed_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'item'))
2889
				{
2890
					$keys = array_keys($items);
2891
					foreach ($keys as $key)
2892
					{
2893
						$this->data['items'][] = $this->registry->create('Item', array($this, $items[$key]));
2894
					}
2895
				}
2896 View Code Duplication
				if ($items = $this->get_feed_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'item'))
2897
				{
2898
					$keys = array_keys($items);
2899
					foreach ($keys as $key)
2900
					{
2901
						$this->data['items'][] = $this->registry->create('Item', array($this, $items[$key]));
2902
					}
2903
				}
2904 View Code Duplication
				if ($items = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'item'))
2905
				{
2906
					$keys = array_keys($items);
2907
					foreach ($keys as $key)
2908
					{
2909
						$this->data['items'][] = $this->registry->create('Item', array($this, $items[$key]));
2910
					}
2911
				}
2912
			}
2913
		}
2914
2915
		if (!empty($this->data['items']))
2916
		{
2917
			// If we want to order it by date, check if all items have a date, and then sort it
2918
			if ($this->order_by_date && empty($this->multifeed_objects))
2919
			{
2920
				if (!isset($this->data['ordered_items']))
2921
				{
2922
					$do_sort = true;
2923
					foreach ($this->data['items'] as $item)
2924
					{
2925
						if (!$item->get_date('U'))
2926
						{
2927
							$do_sort = false;
2928
							break;
2929
						}
2930
					}
2931
					$item = null;
2932
					$this->data['ordered_items'] = $this->data['items'];
2933
					if ($do_sort)
2934
					{
2935
						usort($this->data['ordered_items'], array(get_class($this), 'sort_items'));
2936
					}
2937
				}
2938
				$items = $this->data['ordered_items'];
2939
			}
2940
			else
2941
			{
2942
				$items = $this->data['items'];
2943
			}
2944
2945
			// Slice the data as desired
2946 View Code Duplication
			if ($end === 0)
2947
			{
2948
				return array_slice($items, $start);
2949
			}
2950
			else
2951
			{
2952
				return array_slice($items, $start, $end);
2953
			}
2954
		}
2955
		else
2956
		{
2957
			return array();
2958
		}
2959
	}
2960
2961
	/**
2962
	 * Set the favicon handler
2963
	 *
2964
	 * @deprecated Use your own favicon handling instead
2965
	 */
2966
	public function set_favicon_handler($page = false, $qs = 'i')
0 ignored issues
show
The parameter $page is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
The parameter $qs is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
2967
	{
2968
		$level = defined('E_USER_DEPRECATED') ? E_USER_DEPRECATED : E_USER_WARNING;
2969
		trigger_error('Favicon handling has been removed, please use your own handling', $level);
2970
		return false;
2971
	}
2972
2973
	/**
2974
	 * Get the favicon for the current feed
2975
	 *
2976
	 * @deprecated Use your own favicon handling instead
2977
	 */
2978
	public function get_favicon()
2979
	{
2980
		$level = defined('E_USER_DEPRECATED') ? E_USER_DEPRECATED : E_USER_WARNING;
2981
		trigger_error('Favicon handling has been removed, please use your own handling', $level);
2982
2983
		if (($url = $this->get_link()) !== null)
2984
		{
2985
			return 'http://g.etfv.co/' . urlencode($url);
2986
		}
2987
2988
		return false;
2989
	}
2990
2991
	/**
2992
	 * Magic method handler
2993
	 *
2994
	 * @param string $method Method name
2995
	 * @param array $args Arguments to the method
2996
	 * @return mixed
0 ignored issues
show
Consider making the return type a bit more specific; maybe use string|false|null.

This check looks for the generic type array as a return type and suggests a more specific type. This type is inferred from the actual code.

Loading history...
2997
	 */
2998
	public function __call($method, $args)
2999
	{
3000 View Code Duplication
		if (strpos($method, 'subscribe_') === 0)
3001
		{
3002
			$level = defined('E_USER_DEPRECATED') ? E_USER_DEPRECATED : E_USER_WARNING;
3003
			trigger_error('subscribe_*() has been deprecated, implement the callback yourself', $level);
3004
			return '';
3005
		}
3006 View Code Duplication
		if ($method === 'enable_xml_dump')
3007
		{
3008
			$level = defined('E_USER_DEPRECATED') ? E_USER_DEPRECATED : E_USER_WARNING;
3009
			trigger_error('enable_xml_dump() has been deprecated, use get_raw_data() instead', $level);
3010
			return false;
3011
		}
3012
3013
		$class = get_class($this);
3014
		$trace = debug_backtrace();
3015
		$file = $trace[0]['file'];
3016
		$line = $trace[0]['line'];
3017
		trigger_error("Call to undefined method $class::$method() in $file on line $line", E_USER_ERROR);
3018
	}
3019
3020
	/**
3021
	 * Sorting callback for items
3022
	 *
3023
	 * @access private
3024
	 * @param SimplePie $a
3025
	 * @param SimplePie $b
3026
	 * @return boolean
3027
	 */
3028
	public static function sort_items($a, $b)
3029
	{
3030
		return $a->get_date('U') <= $b->get_date('U');
0 ignored issues
show
Documentation Bug introduced by
The method get_date does not exist on object<SimplePie>? Since you implemented __call, maybe consider adding a @method annotation.

If you implement __call and you know which methods are available, you can improve IDE auto-completion and static analysis by adding a @method annotation to the class.

This is often the case, when __call is implemented by a parent class and only the child class knows which methods exist:

class ParentClass {
    private $data = array();

    public function __call($method, array $args) {
        if (0 === strpos($method, 'get')) {
            return $this->data[strtolower(substr($method, 3))];
        }

        throw new \LogicException(sprintf('Unsupported method: %s', $method));
    }
}

/**
 * If this class knows which fields exist, you can specify the methods here:
 *
 * @method string getName()
 */
class SomeClass extends ParentClass { }
Loading history...
3031
	}
3032
3033
	/**
3034
	 * Merge items from several feeds into one
3035
	 *
3036
	 * If you're merging multiple feeds together, they need to all have dates
3037
	 * for the items or else SimplePie will refuse to sort them.
3038
	 *
3039
	 * @link http://simplepie.org/wiki/tutorial/sort_multiple_feeds_by_time_and_date#if_feeds_require_separate_per-feed_settings
3040
	 * @param array $urls List of SimplePie feed objects to merge
3041
	 * @param int $start Starting item
3042
	 * @param int $end Number of items to return
3043
	 * @param int $limit Maximum number of items per feed
3044
	 * @return array
3045
	 */
3046
	public static function merge_items($urls, $start = 0, $end = 0, $limit = 0)
3047
	{
3048
		if (is_array($urls) && sizeof($urls) > 0)
3049
		{
3050
			$items = array();
3051
			foreach ($urls as $arg)
3052
			{
3053
				if ($arg instanceof SimplePie)
3054
				{
3055
					$items = array_merge($items, $arg->get_items(0, $limit));
3056
				}
3057
				else
3058
				{
3059
					trigger_error('Arguments must be SimplePie objects', E_USER_WARNING);
3060
				}
3061
			}
3062
3063
			$do_sort = true;
3064
			foreach ($items as $item)
3065
			{
3066
				if (!$item->get_date('U'))
3067
				{
3068
					$do_sort = false;
3069
					break;
3070
				}
3071
			}
3072
			$item = null;
3073
			if ($do_sort)
3074
			{
3075
				usort($items, array(get_class($urls[0]), 'sort_items'));
3076
			}
3077
3078 View Code Duplication
			if ($end === 0)
3079
			{
3080
				return array_slice($items, $start);
3081
			}
3082
			else
3083
			{
3084
				return array_slice($items, $start, $end);
3085
			}
3086
		}
3087
		else
3088
		{
3089
			trigger_error('Cannot merge zero SimplePie objects', E_USER_WARNING);
3090
			return array();
3091
		}
3092
	}
3093
}
3094
endif;