Passed
Branch develop (01f96b)
by
unknown
30:45
created

RssParser::getAtomItemDescription()   A

Complexity

Conditions 4
Paths 6

Size

Total Lines 26
Code Lines 11

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 4
eloc 11
c 1
b 0
f 0
nc 6
nop 2
dl 0
loc 26
rs 9.9
1
<?php
2
/* Copyright (C) 2011-2012 Laurent Destailleur  <[email protected]>
3
 *
4
* This program is free software; you can redistribute it and/or modify
5
* it under the terms of the GNU General Public License as published by
6
* the Free Software Foundation; either version 3 of the License, or
7
* (at your option) any later version.
8
*
9
* This program is distributed in the hope that it will be useful,
10
* but WITHOUT ANY WARRANTY; without even the implied warranty of
11
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12
* GNU General Public License for more details.
13
*
14
* You should have received a copy of the GNU General Public License
15
* along with this program. If not, see <https://www.gnu.org/licenses/>.
16
*/
17
18
/**
19
 *      \file       htdocs/core/class/rssparser.class.php
20
 *      \ingroup    core
21
 *      \brief      File of class to parse RSS feeds
22
 */
23
24
/**
25
 * 	Class to parse RSS files
26
 */
27
class RssParser
28
{
29
	/**
30
	 * @var DoliDB Database handler.
31
	 */
32
	public $db;
33
34
	/**
35
	 * @var string Error code (or message)
36
	 */
37
	public $error = '';
38
39
	private $_format = '';
40
	private $_urlRSS;
41
	private $_language;
42
	private $_generator;
43
	private $_copyright;
44
	private $_lastbuilddate;
45
	private $_imageurl;
46
	private $_link;
47
	private $_title;
48
	private $_description;
49
	private $_lastfetchdate; // Last successful fetch
50
	private $_rssarray = array();
51
52
	// For parsing with xmlparser
53
	public $stack = array(); // parser stack
54
	private $_CONTENT_CONSTRUCTS = array('content', 'summary', 'info', 'title', 'tagline', 'copyright');
55
56
57
	/**
58
	 *	Constructor
59
	 *
60
	 *  @param		DoliDB		$db      Database handler
61
	 */
62
	public function __construct($db)
63
	{
64
		$this->db = $db;
65
	}
66
67
	/**
68
	 * getFormat
69
	 *
70
	 * @return string
71
	 */
72
	public function getFormat()
73
	{
74
		return $this->_format;
75
	}
76
77
	/**
78
	 * getUrlRss
79
	 *
80
	 * @return string
81
	 */
82
	public function getUrlRss()
83
	{
84
		return $this->_urlRSS;
85
	}
86
	/**
87
	 * getLanguage
88
	 *
89
	 * @return string
90
	 */
91
	public function getLanguage()
92
	{
93
		return $this->_language;
94
	}
95
	/**
96
	 * getGenerator
97
	 *
98
	 * @return string
99
	 */
100
	public function getGenerator()
101
	{
102
		return $this->_generator;
103
	}
104
	/**
105
	 * getCopyright
106
	 *
107
	 * @return string
108
	 */
109
	public function getCopyright()
110
	{
111
		return $this->_copyright;
112
	}
113
	/**
114
	 * getLastBuildDate
115
	 *
116
	 * @return string
117
	 */
118
	public function getLastBuildDate()
119
	{
120
		return $this->_lastbuilddate;
121
	}
122
	/**
123
	 * getImageUrl
124
	 *
125
	 * @return string
126
	 */
127
	public function getImageUrl()
128
	{
129
		return $this->_imageurl;
130
	}
131
	/**
132
	 * getLink
133
	 *
134
	 * @return string
135
	 */
136
	public function getLink()
137
	{
138
		return $this->_link;
139
	}
140
	/**
141
	 * getTitle
142
	 *
143
	 * @return string
144
	 */
145
	public function getTitle()
146
	{
147
		return $this->_title;
148
	}
149
	/**
150
	 * getDescription
151
	 *
152
	 * @return string
153
	 */
154
	public function getDescription()
155
	{
156
		return $this->_description;
157
	}
158
	/**
159
	 * getLastFetchDate
160
	 *
161
	 * @return string
162
	 */
163
	public function getLastFetchDate()
164
	{
165
		return $this->_lastfetchdate;
166
	}
167
	/**
168
	 * getItems
169
	 *
170
	 * @return string
171
	 */
172
	public function getItems()
173
	{
174
		return $this->_rssarray;
175
	}
176
177
178
	/**
179
	 * 	Parse rss URL
180
	 *
181
	 * 	@param	string	$urlRSS		Url to parse
182
	 * 	@param	int		$maxNb		Max nb of records to get (0 for no limit)
183
	 * 	@param	int		$cachedelay	0=No cache, nb of seconds we accept cache files (cachedir must also be defined)
184
	 * 	@param	string	$cachedir	Directory where to save cache file
185
	 *	@return	int					<0 if KO, >0 if OK
186
	 */
187
	public function parser($urlRSS, $maxNb = 0, $cachedelay = 60, $cachedir = '')
188
	{
189
		global $conf;
190
191
		include_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php';
192
193
		$rss = '';
194
		$str = ''; // This will contain content of feed
195
196
		// Check parameters
197
		if (!dol_is_url($urlRSS))
198
		{
199
			$this->error = "ErrorBadUrl";
200
			return -1;
201
		}
202
203
		$this->_urlRSS = $urlRSS;
204
		$newpathofdestfile = $cachedir.'/'.dol_hash($this->_urlRSS, 3); // Force md5 hash (does not contains special chars)
205
		$newmask = '0644';
206
207
		//dol_syslog("RssPArser::parser parse url=".$urlRSS." => cache file=".$newpathofdestfile);
208
		$nowgmt = dol_now();
209
210
		// Search into cache
211
		$foundintocache = 0;
212
		if ($cachedelay > 0 && $cachedir)
213
		{
214
			$filedate = dol_filemtime($newpathofdestfile);
215
			if ($filedate >= ($nowgmt - $cachedelay))
216
			{
217
				//dol_syslog("RssParser::parser cache file ".$newpathofdestfile." is not older than now - cachedelay (".$nowgmt." - ".$cachedelay.") so we use it.");
218
				$foundintocache = 1;
219
220
				$this->_lastfetchdate = $filedate;
221
			}
222
			else
223
			{
224
				dol_syslog(get_class($this)."::parser cache file ".$newpathofdestfile." is not found or older than now - cachedelay (".$nowgmt." - ".$cachedelay.") so we can't use it.");
225
			}
226
		}
227
228
		// Load file into $str
229
		if ($foundintocache)    // Cache file found and is not too old
230
		{
231
			$str = file_get_contents($newpathofdestfile);
232
		}
233
		else
234
		{
235
			try {
236
				ini_set("user_agent", "Dolibarr ERP-CRM RSS reader");
237
				ini_set("max_execution_time", $conf->global->MAIN_USE_RESPONSE_TIMEOUT);
238
				ini_set("default_socket_timeout", $conf->global->MAIN_USE_RESPONSE_TIMEOUT);
239
240
				$opts = array('http'=>array('method'=>"GET"));
241
				if (!empty($conf->global->MAIN_USE_CONNECT_TIMEOUT)) $opts['http']['timeout'] = $conf->global->MAIN_USE_CONNECT_TIMEOUT;
242
				if (!empty($conf->global->MAIN_PROXY_USE))           $opts['http']['proxy'] = 'tcp://'.$conf->global->MAIN_PROXY_HOST.':'.$conf->global->MAIN_PROXY_PORT;
243
				//var_dump($opts);exit;
244
				$context = stream_context_create($opts);
245
246
				$str = file_get_contents($this->_urlRSS, false, $context);
247
			}
248
			catch (Exception $e) {
249
				print 'Error retrieving URL '.$this->_urlRSS.' - '.$e->getMessage();
250
			}
251
		}
252
253
		if ($str !== false)
254
		{
255
			// Convert $str into xml
256
			if (!empty($conf->global->EXTERNALRSS_USE_SIMPLEXML))
257
			{
258
				//print 'xx'.LIBXML_NOCDATA;
259
				libxml_use_internal_errors(false);
260
				$rss = simplexml_load_string($str, "SimpleXMLElement", LIBXML_NOCDATA);
261
			}
262
			else
263
			{
264
				$xmlparser = xml_parser_create('');
265
				if (!is_resource($xmlparser)) {
266
					$this->error = "ErrorFailedToCreateParser"; return -1;
267
				}
268
269
				xml_set_object($xmlparser, $this);
270
				xml_set_element_handler($xmlparser, 'feed_start_element', 'feed_end_element');
271
				xml_set_character_data_handler($xmlparser, 'feed_cdata');
272
				$status = xml_parse($xmlparser, $str);
273
				xml_parser_free($xmlparser);
274
				$rss = $this;
275
				//var_dump($rss->_format);exit;
276
			}
277
		}
278
279
		// If $rss loaded
280
		if ($rss)
281
		{
282
			// Save file into cache
283
			if (empty($foundintocache) && $cachedir)
284
			{
285
				dol_syslog(get_class($this)."::parser cache file ".$newpathofdestfile." is saved onto disk.");
286
				if (!dol_is_dir($cachedir)) dol_mkdir($cachedir);
287
				$fp = fopen($newpathofdestfile, 'w');
288
				if ($fp)
289
				{
290
					fwrite($fp, $str);
291
					fclose($fp);
292
					if (!empty($conf->global->MAIN_UMASK)) $newmask = $conf->global->MAIN_UMASK;
293
					@chmod($newpathofdestfile, octdec($newmask));
294
295
					$this->_lastfetchdate = $nowgmt;
296
				}
297
				else
298
				{
299
					print 'Error, failed to open file '.$newpathofdestfile.' for write';
300
				}
301
			}
302
303
			unset($str); // Free memory
304
305
			if (empty($rss->_format))    // If format not detected automatically
306
			{
307
				$rss->_format = 'rss';
0 ignored issues
show
Bug introduced by
The property _format does not seem to exist on SimpleXMLElement.
Loading history...
308
				if (empty($rss->channel)) $rss->_format = 'atom';
309
			}
310
311
			$items = array();
312
313
			// Save description entries
314
			if ($rss->_format == 'rss')
315
			{
316
				//var_dump($rss);
317
				if (!empty($conf->global->EXTERNALRSS_USE_SIMPLEXML))
318
				{
319
					if (!empty($rss->channel->language))      $this->_language = (string) $rss->channel->language;
320
					if (!empty($rss->channel->generator))     $this->_generator = (string) $rss->channel->generator;
321
					if (!empty($rss->channel->copyright))     $this->_copyright = (string) $rss->channel->copyright;
322
					if (!empty($rss->channel->lastbuilddate)) $this->_lastbuilddate = (string) $rss->channel->lastbuilddate;
323
					if (!empty($rss->channel->image->url[0])) $this->_imageurl = (string) $rss->channel->image->url[0];
324
					if (!empty($rss->channel->link))		  $this->_link = (string) $rss->channel->link;
325
					if (!empty($rss->channel->title))         $this->_title = (string) $rss->channel->title;
326
					if (!empty($rss->channel->description))	  $this->_description = (string) $rss->channel->description;
327
				}
328
				else
329
				{
330
					//var_dump($rss->channel);
331
					if (!empty($rss->channel['language']))      $this->_language = (string) $rss->channel['language'];
332
					if (!empty($rss->channel['generator']))     $this->_generator = (string) $rss->channel['generator'];
333
					if (!empty($rss->channel['copyright']))     $this->_copyright = (string) $rss->channel['copyright'];
334
					if (!empty($rss->channel['lastbuilddate'])) $this->_lastbuilddate = (string) $rss->channel['lastbuilddate'];
335
					if (!empty($rss->image['url']))             $this->_imageurl = (string) $rss->image['url'];
336
					if (!empty($rss->channel['link']))		    $this->_link = (string) $rss->channel['link'];
337
					if (!empty($rss->channel['title']))         $this->_title = (string) $rss->channel['title'];
338
					if (!empty($rss->channel['description']))   $this->_description = (string) $rss->channel['description'];
339
				}
340
341
				if (!empty($conf->global->EXTERNALRSS_USE_SIMPLEXML)) $items = $rss->channel->item; // With simplexml
342
				else $items = $rss->items; // With xmlparse
343
				//var_dump($items);exit;
344
			}
345
			elseif ($rss->_format == 'atom')
346
			{
347
				//var_dump($rss);
348
				if (!empty($conf->global->EXTERNALRSS_USE_SIMPLEXML))
349
				{
350
					if (!empty($rss->generator))     $this->_generator = (string) $rss->generator;
351
					if (!empty($rss->lastbuilddate)) $this->_lastbuilddate = (string) $rss->modified;
352
					if (!empty($rss->link->href))    $this->_link = (string) $rss->link->href;
353
					if (!empty($rss->title))         $this->_title = (string) $rss->title;
354
					if (!empty($rss->description))	 $this->_description = (string) $rss->description;
355
				}
356
				else
357
				{
358
					//if (!empty($rss->channel['rss_language']))	$this->_language = (string) $rss->channel['rss_language'];
359
					if (!empty($rss->channel['generator']))			$this->_generator = (string) $rss->channel['generator'];
360
					//if (!empty($rss->channel['rss_copyright']))	$this->_copyright = (string) $rss->channel['rss_copyright'];
361
					if (!empty($rss->channel['modified']))			$this->_lastbuilddate = (string) $rss->channel['modified'];
362
					//if (!empty($rss->image['rss_url']))			$this->_imageurl = (string) $rss->image['rss_url'];
363
					if (!empty($rss->channel['link']))				$this->_link = (string) $rss->channel['link'];
364
					if (!empty($rss->channel['title']))				$this->_title = (string) $rss->channel['title'];
365
					//if (!empty($rss->channel['rss_description']))	$this->_description = (string) $rss->channel['rss_description'];
366
367
					$this->_imageurl = $this->getAtomImageUrl($rss->channel);
368
				}
369
				if (!empty($conf->global->EXTERNALRSS_USE_SIMPLEXML)) {
370
					$tmprss = xml2php($rss); $items = $tmprss['entry'];
0 ignored issues
show
Bug introduced by
Are you sure the assignment to $tmprss is correct as xml2php($rss) seems to always return null.

This check looks for function or method calls that always return null and whose return value is assigned to a variable.

class A
{
    function getObject()
    {
        return null;
    }

}

$a = new A();
$object = $a->getObject();

The method getObject() can return nothing but null, so it makes no sense to assign that value to a variable.

The reason is most likely that a function or method is imcomplete or has been reduced for debug purposes.

Loading history...
371
				} // With simplexml
372
				else $items = $rss->items; // With xmlparse
373
				//var_dump($items);exit;
374
			}
375
376
			$i = 0;
377
378
			// Loop on each record
379
			if (is_array($items))
380
			{
381
				foreach ($items as $item)
382
				{
383
					//var_dump($item);exit;
384
					if ($rss->_format == 'rss')
385
					{
386
						if (!empty($conf->global->EXTERNALRSS_USE_SIMPLEXML))
387
						{
388
							$itemLink = (string) $item->link;
389
							$itemTitle = (string) $item->title;
390
							$itemDescription = (string) $item->description;
391
							$itemPubDate = (string) $item->pubDate;
392
							$itemId = '';
393
							$itemAuthor = '';
394
						}
395
						else
396
						{
397
							$itemLink = (string) $item['link'];
398
							$itemTitle = (string) $item['title'];
399
							$itemDescription = (string) $item['description'];
400
							$itemPubDate = (string) $item['pubdate'];
401
							$itemId = (string) $item['guid'];
402
							$itemAuthor = (string) $item['author'];
403
						}
404
405
						// Loop on each category
406
						$itemCategory = array();
407
						if (is_array($item->category))
408
						{
409
							foreach ($item->category as $cat)
410
							{
411
								$itemCategory[] = (string) $cat;
412
							}
413
						}
414
					}
415
					elseif ($rss->_format == 'atom')
416
					{
417
						if (!empty($conf->global->EXTERNALRSS_USE_SIMPLEXML))
418
						{
419
							$itemLink = (isset($item['link']) ? (string) $item['link'] : '');
420
							$itemTitle = (string) $item['title'];
421
							$itemDescription = $this->getAtomItemDescription($item);
422
							$itemPubDate = (string) $item['created'];
423
							$itemId = (string) $item['id'];
424
							$itemAuthor = (string) ($item['author'] ? $item['author'] : $item['author_name']);
425
						}
426
						else
427
						{
428
							$itemLink = (isset($item['link']) ? (string) $item['link'] : '');
429
							$itemTitle = (string) $item['title'];
430
							$itemDescription = $this->getAtomItemDescription($item);
431
							$itemPubDate = (string) $item['created'];
432
							$itemId = (string) $item['id'];
433
							$itemAuthor = (string) ($item['author'] ? $item['author'] : $item['author_name']);
434
						}
435
					}
436
					else print 'ErrorBadFeedFormat';
437
438
					// Add record to result array
439
					$this->_rssarray[$i] = array(
440
						'link'=>$itemLink,
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $itemLink does not seem to be defined for all execution paths leading up to this point.
Loading history...
441
						'title'=>$itemTitle,
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $itemTitle does not seem to be defined for all execution paths leading up to this point.
Loading history...
442
						'description'=>$itemDescription,
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $itemDescription does not seem to be defined for all execution paths leading up to this point.
Loading history...
443
						'pubDate'=>$itemPubDate,
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $itemPubDate does not seem to be defined for all execution paths leading up to this point.
Loading history...
444
						'category'=>$itemCategory,
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $itemCategory does not seem to be defined for all execution paths leading up to this point.
Loading history...
445
						'id'=>$itemId,
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $itemId does not seem to be defined for all execution paths leading up to this point.
Loading history...
446
						'author'=>$itemAuthor);
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $itemAuthor does not seem to be defined for all execution paths leading up to this point.
Loading history...
447
					//var_dump($this->_rssarray);
448
449
					$i++;
450
451
					if ($i > $maxNb)    break; // We get all records we want
452
				}
453
			}
454
455
			return 1;
456
		}
457
		else
458
		{
459
			$this->error = 'ErrorFailedToLoadRSSFile';
460
			return -1;
461
		}
462
	}
463
464
465
466
	// phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
467
	/**
468
	 * 	Triggered when opened tag is found
469
	 *
470
	 * 	@param	string		$p			Start
471
	 *  @param	string		$element	Tag
472
	 *  @param	array		$attrs		Attributes of tags
473
	 *  @return	void
474
	 */
475
	public function feed_start_element($p, $element, &$attrs)
476
	{
477
		// phpcs:enable
478
		$el = $element = strtolower($element);
479
		$attrs = array_change_key_case($attrs, CASE_LOWER);
480
481
		// check for a namespace, and split if found
482
		$ns = false;
483
		if (strpos($element, ':'))
484
		{
485
			list($ns, $el) = explode(':', $element, 2);
486
		}
487
		if ($ns and $ns != 'rdf')
488
		{
489
			$this->current_namespace = $ns;
490
		}
491
492
		// if feed type isn't set, then this is first element of feed identify feed from root element
493
		if (empty($this->_format))
494
		{
495
			if ($el == 'rdf') {
496
				$this->_format = 'rss';
497
				$this->feed_version = '1.0';
498
			}
499
			elseif ($el == 'rss') {
500
				$this->_format = 'rss';
501
				$this->feed_version = $attrs['version'];
502
			}
503
			elseif ($el == 'feed') {
504
				$this->_format = 'atom';
505
				$this->feed_version = $attrs['version'];
506
				$this->inchannel = true;
507
			}
508
			return;
509
		}
510
511
		if ($el == 'channel')
512
		{
513
			$this->inchannel = true;
514
		}
515
		elseif ($el == 'item' or $el == 'entry')
516
		{
517
			$this->initem = true;
518
			if (isset($attrs['rdf:about'])) {
519
				$this->current_item['about'] = $attrs['rdf:about'];
520
			}
521
		}
522
523
		// if we're in the default namespace of an RSS feed,
524
		//  record textinput or image fields
525
		elseif (
526
		$this->_format == 'rss' and
527
		$this->current_namespace == '' and
528
		$el == 'textinput' )
529
		{
530
			$this->intextinput = true;
531
		}
532
533
		elseif (
534
		$this->_format == 'rss' and
535
		$this->current_namespace == '' and
536
		$el == 'image' )
537
		{
538
			$this->inimage = true;
539
		}
540
541
		// handle atom content constructs
542
		elseif ($this->_format == 'atom' and in_array($el, $this->_CONTENT_CONSTRUCTS))
543
		{
544
			// avoid clashing w/ RSS mod_content
545
			if ($el == 'content') {
546
				$el = 'atom_content';
547
			}
548
549
			$this->incontent = $el;
550
		}
551
552
		// if inside an Atom content construct (e.g. content or summary) field treat tags as text
553
		elseif ($this->_format == 'atom' and $this->incontent)
554
		{
555
			// if tags are inlined, then flatten
556
			$attrs_str = join(' ', array_map('map_attrs', array_keys($attrs), array_values($attrs)));
557
558
			$this->append_content("<$element $attrs_str>");
559
560
			array_unshift($this->stack, $el);
561
		}
562
563
		// Atom support many links per containging element.
564
		// Magpie treats link elements of type rel='alternate'
565
		// as being equivalent to RSS's simple link element.
566
		//
567
		elseif ($this->_format == 'atom' and $el == 'link')
568
		{
569
			if (isset($attrs['rel']) && $attrs['rel'] == 'alternate')
570
			{
571
				$link_el = 'link';
572
			}
573
			elseif (!isset($attrs['rel']))
574
			{
575
				$link_el = 'link';
576
			}
577
			else
578
			{
579
				$link_el = 'link_'.$attrs['rel'];
580
			}
581
582
			$this->append($link_el, $attrs['href']);
583
		}
584
		// set stack[0] to current element
585
		else {
586
			array_unshift($this->stack, $el);
587
		}
588
	}
589
590
591
	// phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
592
	/**
593
	 * 	Triggered when CDATA is found
594
	 *
595
	 * 	@param	string	$p		P
596
	 *  @param	string	$text	Tag
597
	 *  @return	void
598
	 */
599
	public function feed_cdata($p, $text)
600
	{
601
		// phpcs:enable
602
		if ($this->_format == 'atom' and $this->incontent)
603
		{
604
			$this->append_content($text);
605
		}
606
		else
607
		{
608
			$current_el = join('_', array_reverse($this->stack));
609
			$this->append($current_el, $text);
610
		}
611
	}
612
613
	// phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
614
	/**
615
	 * 	Triggered when closed tag is found
616
	 *
617
	 * 	@param	string		$p		P
618
	 *  @param	string		$el		Tag
619
	 *  @return	void
620
	 */
621
	public function feed_end_element($p, $el)
622
	{
623
		// phpcs:enable
624
		$el = strtolower($el);
625
626
		if ($el == 'item' or $el == 'entry')
627
		{
628
			$this->items[] = $this->current_item;
629
			$this->current_item = array();
630
			$this->initem = false;
631
		}
632
		elseif ($this->_format == 'rss' and $this->current_namespace == '' and $el == 'textinput')
633
		{
634
			$this->intextinput = false;
635
		}
636
		elseif ($this->_format == 'rss' and $this->current_namespace == '' and $el == 'image')
637
		{
638
			$this->inimage = false;
639
		}
640
		elseif ($this->_format == 'atom' and in_array($el, $this->_CONTENT_CONSTRUCTS))
641
		{
642
			$this->incontent = false;
643
		}
644
		elseif ($el == 'channel' or $el == 'feed')
645
		{
646
			$this->inchannel = false;
647
		}
648
		elseif ($this->_format == 'atom' and $this->incontent) {
649
			// balance tags properly
650
			// note:  i don't think this is actually neccessary
651
			if ($this->stack[0] == $el)
652
			{
653
				$this->append_content("</$el>");
654
			}
655
			else {
656
				$this->append_content("<$el />");
657
			}
658
659
			array_shift($this->stack);
660
		}
661
		else {
662
			array_shift($this->stack);
663
		}
664
665
		$this->current_namespace = false;
666
	}
667
668
669
	/**
670
	 * 	To concat 2 string with no warning if an operand is not defined
671
	 *
672
	 * 	@param	string	$str1		Str1
673
	 *  @param	string	$str2		Str2
674
	 *  @return	string				String cancatenated
675
	 */
676
	public function concat(&$str1, $str2 = "")
677
	{
678
		if (!isset($str1)) {
679
			$str1 = "";
680
		}
681
		$str1 .= $str2;
682
	}
683
684
	// phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
685
	/**
686
	 * Enter description here ...
687
	 *
688
	 * @param	string	$text		Text
689
	 * @return	void
690
	 */
691
	public function append_content($text)
692
	{
693
		// phpcs:enable
694
		if ($this->initem) {
695
			$this->concat($this->current_item[$this->incontent], $text);
696
		}
697
		elseif ($this->inchannel) {
698
			$this->concat($this->channel[$this->incontent], $text);
0 ignored issues
show
Bug introduced by
The property channel does not exist on RssParser. Did you mean inchannel?
Loading history...
699
		}
700
	}
701
702
	/**
703
	 * 	smart append - field and namespace aware
704
	 *
705
	 * 	@param	string	$el		El
706
	 * 	@param	string	$text	Text
707
	 * 	@return	void
708
	 */
709
	public function append($el, $text)
710
	{
711
		if (!$el) {
712
			return;
713
		}
714
		if ($this->current_namespace)
715
		{
716
			if ($this->initem) {
717
				$this->concat($this->current_item[$this->current_namespace][$el], $text);
718
			}
719
			elseif ($this->inchannel) {
720
				$this->concat($this->channel[$this->current_namespace][$el], $text);
0 ignored issues
show
Bug introduced by
The property channel does not exist on RssParser. Did you mean inchannel?
Loading history...
721
			}
722
			elseif ($this->intextinput) {
723
				$this->concat($this->textinput[$this->current_namespace][$el], $text);
0 ignored issues
show
Bug introduced by
The property textinput does not exist on RssParser. Did you mean intextinput?
Loading history...
724
			}
725
			elseif ($this->inimage) {
726
				$this->concat($this->image[$this->current_namespace][$el], $text);
0 ignored issues
show
Bug introduced by
The property image does not exist on RssParser. Did you mean inimage?
Loading history...
727
			}
728
		}
729
		else {
730
			if ($this->initem) {
731
				$this->concat($this->current_item[$el], $text);
732
			}
733
			elseif ($this->intextinput) {
734
				$this->concat($this->textinput[$el], $text);
735
			}
736
			elseif ($this->inimage) {
737
				$this->concat($this->image[$el], $text);
738
			}
739
			elseif ($this->inchannel) {
740
				$this->concat($this->channel[$el], $text);
741
			}
742
		}
743
	}
744
745
	/**
746
	 * Return a description/summary for one item from a ATOM feed
747
	 *
748
	 * @param	array	$item		A parsed item of a ATOM feed
749
	 * @param	int		$maxlength	(optional) The maximum length for the description
750
	 * @return	string				A summary description
751
	 */
752
	private function getAtomItemDescription(array $item, $maxlength = 500)
753
	{
754
		$result = "";
755
756
		if (isset($item['summary']))
757
		{
758
			$result = $item['summary'];
759
		}
760
		elseif (isset($item['atom_content']))
761
		{
762
			$result = $item['atom_content'];
763
		}
764
765
		// remove all HTML elements that can possible break the maximum size of a tooltip,
766
		// like headings, image, video etc. and allow only simple style elements
767
		$result = strip_tags($result, "<br><p><ul><ol><li>");
768
769
		$result = str_replace("\n", "", $result);
770
771
		if (strlen($result) > $maxlength)
772
		{
773
			$result = substr($result, 0, $maxlength);
774
			$result .= "...";
775
		}
776
777
		return $result;
778
	}
779
780
	/**
781
	 * Return a URL to a image of the given ATOM feed
782
	 *
783
	 * @param	array	$feed	The ATOM feed that possible contain a link to a logo or icon
784
	 * @return	string			A URL to a image from a ATOM feed when found, otherwise a empty string
785
	 */
786
	private function getAtomImageUrl(array $feed)
787
	{
788
		if (isset($feed['icon']))
789
		{
790
			return $feed['logo'];
791
		}
792
793
		if (isset($feed['icon']))
794
		{
795
			return $feed['logo'];
796
		}
797
798
		if (isset($feed['webfeeds:logo']))
799
		{
800
			return $feed['webfeeds:logo'];
801
		}
802
803
		if (isset($feed['webfeeds:icon']))
804
		{
805
			return $feed['webfeeds:icon'];
806
		}
807
808
		if (isset($feed['webfeeds:wordmark']))
809
		{
810
			return $feed['webfeeds:wordmark'];
811
		}
812
813
		return "";
814
	}
815
}
816
817
818
/**
819
 * Function to convert an XML object into an array
820
 *
821
 * @param	SimpleXMLElement	$xml		Xml
822
 * @return	void
823
 */
824
function xml2php($xml)
825
{
826
	$fils = 0;
827
	$tab = false;
828
	$array = array();
829
	foreach ($xml->children() as $key => $value)
830
	{
831
		$child = xml2php($value);
0 ignored issues
show
Bug introduced by
Are you sure the assignment to $child is correct as xml2php($value) seems to always return null.

This check looks for function or method calls that always return null and whose return value is assigned to a variable.

class A
{
    function getObject()
    {
        return null;
    }

}

$a = new A();
$object = $a->getObject();

The method getObject() can return nothing but null, so it makes no sense to assign that value to a variable.

The reason is most likely that a function or method is imcomplete or has been reduced for debug purposes.

Loading history...
832
833
		//To deal with the attributes
834
		foreach ($value->attributes() as $ak=>$av)
835
		{
836
			$child[$ak] = (string) $av;
837
		}
838
839
		//Let see if the new child is not in the array
840
		if ($tab === false && in_array($key, array_keys($array)))
841
		{
842
			//If this element is already in the array we will create an indexed array
843
			$tmp = $array[$key];
844
			$array[$key] = null;
845
			$array[$key][] = $tmp;
846
			$array[$key][] = $child;
847
			$tab = true;
848
		}
849
		elseif ($tab === true)
850
		{
851
			//Add an element in an existing array
852
			$array[$key][] = $child;
853
		}
854
		else
855
		{
856
			//Add a simple element
857
			$array[$key] = $child;
858
		}
859
860
		$fils++;
861
	}
862
863
864
	if ($fils == 0)
865
	{
866
		return (string) $xml;
867
	}
868
869
	return $array;
870
}
871