UniversalFeedCreator::_setFormat()   C
last analyzed

Complexity

Conditions 16
Paths 30

Size

Total Lines 64

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 16
nc 30
nop 1
dl 0
loc 64
rs 5.5666
c 0
b 0
f 0

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
//
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 2 of the License, or        //
7
// (at your option) any later version.                                      //
8
//                                                                          //
9
// You may not change or alter any portion of this comment or credits       //
10
// of supporting developers from this source code or any supporting         //
11
// source code which is considered copyrighted (c) material of the          //
12
// original comment or credit authors.                                      //
13
//                                                                          //
14
// This program is distributed in the hope that it will be useful,          //
15
// but WITHOUT ANY WARRANTY; without even the implied warranty of           //
16
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the            //
17
// GNU General Public License for more details.                             //
18
//                                                                          //
19
// You should have received a copy of the GNU General Public License        //
20
// along with this program; if not, write to the Free Software              //
21
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA //
22
// ------------------------------------------------------------------------ //
23
// Author: phppp (D.J., [email protected])                                  //
24
// URL: https://xoops.org                         //
25
// Project: Article Project                                                 //
26
// ------------------------------------------------------------------------ //
27
28
/*
29
30
FeedCreator class v1.7.2
31
originally (c) Kai Blankenhorn
32
www.bitfolge.de
33
[email protected]
34
v1.3 work by Scott Reynen ([email protected]) and Kai Blankenhorn
35
v1.5 OPML support by Dirk Clemens
36
37
This library is free software; you can redistribute it and/or
38
modify it under the terms of the GNU Lesser General Public
39
License as published by the Free Software Foundation; either
40
version 2.1 of the License, or (at your option) any later version.
41
42
This library is distributed in the hope that it will be useful,
43
but WITHOUT ANY WARRANTY; without even the implied warranty of
44
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
45
Lesser General Public License for more details.
46
47
You should have received a copy of the GNU Lesser General Public
48
License along with this library; if not, write to the Free Software
49
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
50
51
****************************************************************************
52
53
54
Changelog:
55
56
v1.7.2  10-11-04
57
    license changed to LGPL
58
59
v1.7.1
60
    fixed a syntax bug
61
    fixed left over debug code
62
63
v1.7    07-18-04
64
    added HTML and JavaScript feeds (configurable via CSS) (thanks to Pascal Van Hecke)
65
    added HTML descriptions for all feed formats (thanks to Pascal Van Hecke)
66
    added a switch to select an external stylesheet (thanks to Pascal Van Hecke)
67
    changed default content-type to application/xml
68
    added character encoding setting
69
    fixed numerous smaller bugs (thanks to S�ren Fuhrmann of golem.de)
70
    improved changing ATOM versions handling (thanks to August Trometer)
71
    improved the UniversalFeedCreator's useCached method (thanks to S�ren Fuhrmann of golem.de)
72
    added charset output in HTTP headers (thanks to S�ren Fuhrmann of golem.de)
73
    added Slashdot namespace to RSS 1.0 (thanks to S�ren Fuhrmann of golem.de)
74
75
v1.6    05-10-04
76
    added stylesheet to RSS 1.0 feeds
77
    fixed generator comment (thanks Kevin L. Papendick and Tanguy Pruvot)
78
    fixed RFC822 date bug (thanks Tanguy Pruvot)
79
    added TimeZone customization for RFC8601 (thanks Tanguy Pruvot)
80
    fixed Content-type could be empty (thanks Tanguy Pruvot)
81
    fixed author/creator in RSS1.0 (thanks Tanguy Pruvot)
82
83
v1.6 beta   02-28-04
84
    added Atom 0.3 support (not all features, though)
85
    improved OPML 1.0 support (hopefully - added more elements)
86
    added support for arbitrary additional elements (use with caution)
87
    code beautification :-)
88
    considered beta due to some internal changes
89
90
v1.5.1  01-27-04
91
    fixed some RSS 1.0 glitches (thanks to St�phane Vanpoperynghe)
92
    fixed some inconsistencies between documentation and code (thanks to Timothy Martin)
93
94
v1.5    01-06-04
95
    added support for OPML 1.0
96
    added more documentation
97
98
v1.4    11-11-03
99
    optional feed saving and caching
100
    improved documentation
101
    minor improvements
102
103
v1.3    10-02-03
104
    renamed to FeedCreator, as it not only creates RSS anymore
105
    added support for mbox
106
    tentative support for echo/necho/atom/pie/???
107
108
v1.2    07-20-03
109
    intelligent auto-truncating of RSS 0.91 attributes
110
    don't create some attributes when they're not set
111
    documentation improved
112
    fixed a real and a possible bug with date conversions
113
    code cleanup
114
115
v1.1    06-29-03
116
    added images to feeds
117
    now includes most RSS 0.91 attributes
118
    added RSS 2.0 feeds
119
120
v1.0    06-24-03
121
    initial release
122
123
124
125
***************************************************************************/
126
127
/* ** GENERAL USAGE *********************************************************
128
129
include("feedcreator.class.php");
130
131
$rss = new UniversalFeedCreator();
132
$rss->useCached(); // use cached version if age<1 hour
133
$rss->title = "PHP news";
134
$rss->description = "daily news from the PHP scripting world";
135
136
//optional
137
$rss->descriptionTruncSize = 500;
138
$rss->descriptionHtmlSyndicated = true;
139
140
$rss->link = "http://www.dailyphp.net/news";
141
$rss->syndicationURL = "http://www.dailyphp.net/".$_SERVER["PHP_SELF"];
142
143
$image = new FeedImage();
144
$image->title = "dailyphp.net logo";
145
$image->url = "http://www.dailyphp.net/images/logo.gif";
146
$image->link = "http://www.dailyphp.net";
147
$image->description = "Feed provided by dailyphp.net. Click to visit.";
148
149
//optional
150
$image->descriptionTruncSize = 500;
151
$image->descriptionHtmlSyndicated = true;
152
153
$rss->image = $image;
154
155
// get your news items from somewhere, e.g. your database:
156
mysqli_select_db($GLOBALS['xoopsDB']->conn, $dbHost, $dbUser, $dbPass);
157
$res $GLOBALS['xoopsDB']->query("SELECT * FROM news ORDER BY newsdate DESC");
158
while ($data = $GLOBALS['xoopsDB']->fetchObject($res)) {
159
    $item = new FeedItem();
160
    $item->title = $data->title;
161
    $item->link = $data->url;
162
    $item->description = $data->short;
163
164
    //optional
165
    item->descriptionTruncSize = 500;
166
    item->descriptionHtmlSyndicated = true;
167
168
    $item->date = $data->newsdate;
169
    $item->source = "http://www.dailyphp.net";
170
    $item->author = "John Doe";
171
172
    $rss->addItem($item);
173
}
174
175
// valid format strings are: RSS0.91, RSS1.0, RSS2.0, PIE0.1 (deprecated),
176
// MBOX, OPML, ATOM, ATOM0.3, HTML, JS
177
echo $rss->saveFeed("RSS1.0", "news/feed.xml");
178
179
180
***************************************************************************
181
*          A little setup                                                 *
182
**************************************************************************/
183
184
// your local timezone, set to "" to disable or for GMT
185
//define("TIME_ZONE","+01:00");
186
187
/**
188
 * Version string.
189
 **/
190
//define("FEEDCREATOR_VERSION", "ARTICLE @ XOOPS powered by FeedCreator 1.7.2");
191
192
/**
193
 * A FeedItem is a part of a FeedCreator feed.
194
 *
195
 * @author Kai Blankenhorn <[email protected]>
196
 * @since  1.3
197
 */
198
class FeedItem extends HtmlDescribable
199
{
200
    /**
201
     * Mandatory attributes of an item.
202
     */
203
    public $title;
204
    public $description;
205
    public $link;
206
207
    /**
208
     * Optional attributes of an item.
209
     */
210
    public $author;
211
    public $authorEmail;
212
    public $image;
213
    public $category;
214
    public $comments;
215
    public $guid;
216
    public $source;
217
    public $creator;
218
219
    /**
220
     * Publishing date of an item. May be in one of the following formats:
221
     *
222
     *  RFC 822:
223
     *  "Mon, 20 Jan 03 18:05:41 +0400"
224
     *  "20 Jan 03 18:05:41 +0000"
225
     *
226
     *  ISO 8601:
227
     *  "2003-01-20T18:05:41+04:00"
228
     *
229
     *  Unix:
230
     *  1043082341
231
     */
232
    public $date;
233
234
    /**
235
     * Any additional elements to include as an assiciated array. All $key => $value pairs
236
     * will be included unencoded in the feed item in the form
237
     *     <$key>$value</$key>
238
     * Again: No encoding will be used! This means you can invalidate or enhance the feed
239
     * if $value contains markup. This may be abused to embed tags not implemented by
240
     * the FeedCreator class used.
241
     */
242
    public $additionalElements = [];
243
244
    // on hold
245
    // var $source;
246
}
247
248
/**
249
 * An FeedImage may be added to a FeedCreator feed.
250
 * @author Kai Blankenhorn <[email protected]>
251
 * @since  1.3
252
 */
253
class FeedImage extends HtmlDescribable
254
{
255
    /**
256
     * Mandatory attributes of an image.
257
     */
258
    public $title;
259
    public $url;
260
    public $link;
261
262
    /**
263
     * Optional attributes of an image.
264
     */
265
    public $width;
266
    public $height;
267
    public $description;
268
}
269
270
/**
271
 * An HtmlDescribable is an item within a feed that can have a description that may
272
 * include HTML markup.
273
 */
274
class HtmlDescribable
275
{
276
    /**
277
     * Indicates whether the description field should be rendered in HTML.
278
     */
279
    public $descriptionHtmlSyndicated;
280
281
    /**
282
     * Indicates whether and to how many characters a description should be truncated.
283
     */
284
    public $descriptionTruncSize;
285
286
    /**
287
     * Returns a formatted description field, depending on descriptionHtmlSyndicated and
288
     * $descriptionTruncSize properties
289
     * @return string the formatted description
290
     */
291
    public function getDescription()
292
    {
293
        $descriptionField                = new FeedHtmlField($this->description);
0 ignored issues
show
Bug introduced by
The property description does not seem to exist. Did you mean descriptionHtmlSyndicated?

An attempt at access to an undefined property has been detected. This may either be a typographical error or the property has been renamed but there are still references to its old name.

If you really want to allow access to undefined properties, you can define magic methods to allow access. See the php core documentation on Overloading.

Loading history...
294
        $descriptionField->syndicateHtml = $this->descriptionHtmlSyndicated;
295
        $descriptionField->truncSize     = $this->descriptionTruncSize;
296
297
        return $descriptionField->output();
298
    }
299
}
300
301
/**
302
 * An FeedHtmlField describes and generates
303
 * a feed, item or image html field (probably a description). Output is
304
 * generated based on $truncSize, $syndicateHtml properties.
305
 * @author  Pascal Van Hecke <[email protected]>
306
 */
307
class FeedHtmlField
308
{
309
    /**
310
     * Mandatory attributes of a FeedHtmlField.
311
     */
312
    public $rawFieldContent;
313
314
    /**
315
     * Optional attributes of a FeedHtmlField.
316
     *
317
     */
318
    public $truncSize;
319
    public $syndicateHtml;
320
321
    /**
322
     * Creates a new instance of FeedHtmlField.
323
     * @param $parFieldContent
324
     * @internal param $string : if given, sets the rawFieldContent property
325
     */
326
    public function __construct($parFieldContent)
327
    {
328
        if ($parFieldContent) {
329
            $this->rawFieldContent = $parFieldContent;
330
        }
331
    }
332
333
    /**
334
     * Creates the right output, depending on $truncSize, $syndicateHtml properties.
335
     * @return string the formatted field
336
     */
337
    public function output()
338
    {
339
        // when field available and syndicated in html we assume
340
        // - valid html in $rawFieldContent and we enclose in CDATA tags
341
        // - no truncation (truncating risks producing invalid html)
342
        if (!$this->rawFieldContent) {
343
            $result = '';
344
        } elseif ($this->syndicateHtml) {
345
            $result = '<![CDATA[' . $this->rawFieldContent . ']]>';
346
        } else {
347
            if ($this->truncSize && is_int($this->truncSize)) {
348
                $result = FeedCreator::iTrunc(htmlspecialchars($this->rawFieldContent, ENT_QUOTES | ENT_HTML5), $this->truncSize);
349
            } else {
350
                $result = htmlspecialchars($this->rawFieldContent, ENT_QUOTES | ENT_HTML5);
351
            }
352
        }
353
354
        return $result;
355
    }
356
}
357
358
/**
359
 * UniversalFeedCreator lets you choose during runtime which
360
 * format to build.
361
 * For general usage of a feed class, see the FeedCreator class
362
 * below or the example above.
363
 *
364
 * @since  1.3
365
 * @author Kai Blankenhorn <[email protected]>
366
 */
367
class UniversalFeedCreator extends FeedCreator
368
{
369
    public $_feed;
370
371
    /**
372
     * @param $format
373
     */
374
    public function _setFormat($format)
375
    {
376
        switch (strtoupper($format)) {
377
378
            case '2.0':
379
                // fall through
380
            case 'RSS2.0':
381
                $this->_feed = new RSSCreator20();
382
                break;
383
384
            case '1.0':
385
                // fall through
386
            case 'RSS1.0':
387
                $this->_feed = new RSSCreator10();
388
                break;
389
390
            case '0.91':
391
                // fall through
392
            case 'RSS0.91':
393
                $this->_feed = new RSSCreator091();
394
                break;
395
396
            case 'PIE0.1':
397
                $this->_feed = new PIECreator01();
0 ignored issues
show
Deprecated Code introduced by
The class PIECreator01 has been deprecated.

This class, trait or interface has been deprecated.

Loading history...
398
                break;
399
400
            case 'MBOX':
401
                $this->_feed = new MBOXCreator();
402
                break;
403
404
            case 'OPML':
405
                $this->_feed = new OPMLCreator();
406
                break;
407
408
            case 'ATOM':
409
                // fall through: always the latest ATOM version
410
411
            case 'ATOM0.3':
412
                $this->_feed = new AtomCreator03();
413
                break;
414
415
            case 'HTML':
416
                $this->_feed = new HTMLCreator();
417
                break;
418
419
            case 'JS':
420
                // fall through
421
            case 'JAVASCRIPT':
422
                $this->_feed = new JSCreator();
423
                break;
424
425
            default:
426
                $this->_feed = new RSSCreator091();
427
                break;
428
        }
429
430
        $vars = get_object_vars($this);
431
        foreach ($vars as $key => $value) {
432
            // prevent overwriting of properties "contentType", "encoding"; do not copy "_feed" itself
433
            //if (!in_array($key, array("_feed", "contentType", "encoding"))) {
434
            $this->_feed->{$key} = $this->{$key};
435
            //}
436
        }
437
    }
438
439
    /**
440
     * Creates a syndication feed based on the items previously added.
441
     *
442
     * @see        FeedCreator::addItem()
443
     * @param    string    format    format the feed should comply to. Valid values are:
444
     *                     "PIE0.1", "mbox", "RSS0.91", "RSS1.0", "RSS2.0", "OPML", "ATOM0.3", "HTML", "JS"
445
     * @return string the contents of the feed.
446
     */
447
    public function createFeed($format = 'RSS0.91')
448
    {
449
        $this->_setFormat($format);
450
451
        return $this->_feed->createFeed();
452
    }
453
454
    /**
455
     * Saves this feed as a file on the local disk. After the file is saved, an HTTP redirect
456
     * header may be sent to redirect the use to the newly created file.
457
     * @since    1.4
458
     *
459
     * @param string $format
460
     * @param string $filename
461
     * @param bool   $displayContents displayContents optional    send the content of the file or not. If true, the file will be sent in the body of the response.
462
     * @internal param format $string format the feed should comply to. Valid values are:
463
     *                                "PIE0.1" (deprecated), "mbox", "RSS0.91", "RSS1.0", "RSS2.0", "OPML", "ATOM", "ATOM0.3", "HTML", "JS"
464
     * @internal param filename $string optional    the filename where a recent version of the feed is saved. If not specified, the filename is $_SERVER["PHP_SELF"] with the extension changed to .xml (see _generateFilename()).
465
     */
466
    public function saveFeed($format = 'RSS0.91', $filename = '', $displayContents = true)
467
    {
468
        $this->_setFormat($format);
469
        $this->_feed->saveFeed($filename, $displayContents);
470
    }
471
472
    /**
473
     * Turns on caching and checks if there is a recent version of this feed in the cache.
474
     * If there is, an HTTP redirect header is sent.
475
     * To effectively use caching, you should create the FeedCreator object and call this method
476
     * before anything else, especially before you do the time consuming task to build the feed
477
     * (web fetching, for example).
478
     *
479
     * @param string $format
480
     * @param string $filename
481
     * @param int    $timeout
482
     * @internal param format $string format the feed should comply to. Valid values are:
483
     *                     "PIE0.1" (deprecated), "mbox", "RSS0.91", "RSS1.0", "RSS2.0", "OPML", "ATOM0.3".
484
     * @internal param string $filename optional the filename where a recent version of the feed is saved. If not specified, the filename is $_SERVER["PHP_SELF"] with the extension changed to .xml (see _generateFilename()).
485
     * @internal param int $timeout optional the timeout in seconds before a cached version is refreshed (defaults to 3600 = 1 hour)
486
     */
487
    public function useCached($format = 'RSS0.91', $filename = '', $timeout = 3600)
488
    {
489
        $this->_setFormat($format);
490
        $this->_feed->useCached($filename, $timeout);
491
    }
492
}
493
494
/**
495
 * FeedCreator is the abstract base implementation for concrete
496
 * implementations that implement a specific format of syndication.
497
 *
498
 * @abstract
499
 * @author Kai Blankenhorn <[email protected]>
500
 * @since  1.4
501
 */
502
class FeedCreator extends HtmlDescribable
503
{
504
    /**
505
     * Mandatory attributes of a feed.
506
     */
507
    public $title;
508
    public $description;
509
    public $link;
510
511
    /**
512
     * Optional attributes of a feed.
513
     */
514
    public $syndicationURL;
515
    public $image;
516
    public $language;
517
    public $copyright;
518
    public $pubDate;
519
    public $lastBuildDate;
520
    public $editor;
521
    public $editorEmail;
522
    public $webmaster;
523
    public $category;
524
    public $docs;
525
    public $ttl;
526
    public $rating;
527
    public $skipHours;
528
    public $skipDays;
529
530
    /**
531
     * The url of the external xsl stylesheet used to format the naked rss feed.
532
     * Ignored in the output when empty.
533
     */
534
    public $xslStyleSheet = '';
535
536
    public $cssStyleSheet = '';
537
538
    /**
539
     * @access private
540
     */
541
    public $items = [];
542
543
    /**
544
     * This feed's MIME content type.
545
     * @since  1.4
546
     * @access private
547
     */
548
    public $contentType = 'application/xml';
549
550
    /**
551
     * This feed's character encoding.
552
     * @since 1.6.1
553
     **/
554
    public $encoding = 'ISO-8859-1';
555
556
    /**
557
     * Any additional elements to include as an assiciated array. All $key => $value pairs
558
     * will be included unencoded in the feed in the form
559
     *     <$key>$value</$key>
560
     * Again: No encoding will be used! This means you can invalidate or enhance the feed
561
     * if $value contains markup. This may be abused to embed tags not implemented by
562
     * the FeedCreator class used.
563
     */
564
    public $additionalElements = [];
565
566
    /**
567
     * Adds an FeedItem to the feed.
568
     *
569
     * @param $item
570
     * @internal param FeedItem $object $item The FeedItem to add to the feed.
571
     * @access   public
572
     */
573
    public function addItem($item)
574
    {
575
        $this->items[] = $item;
576
    }
577
578
    /**
579
     * Truncates a string to a certain length at the most sensible point.
580
     * First, if there's a '.' character near the end of the string, the string is truncated after this character.
581
     * If there is no '.', the string is truncated after the last ' ' character.
582
     * If the string is truncated, " ..." is appended.
583
     * If the string is already shorter than $length, it is returned unchanged.
584
     *
585
     * @static
586
     * @param string     string A string to be truncated.
587
     * @param int        length the maximum length the string should be truncated to
588
     * @return string the truncated string
589
     */
590
    public function iTrunc($string, $length)
591
    {
592
        if (strlen($string) <= $length) {
593
            return $string;
594
        }
595
596
        $pos = strrpos($string, '.');
597 View Code Duplication
        if ($pos >= $length - 4) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
598
            $string = substr($string, 0, $length - 4);
599
            $pos    = strrpos($string, '.');
600
        }
601
        if ($pos >= $length * 0.4) {
602
            return substr($string, 0, $pos + 1) . ' ...';
603
        }
604
605
        $pos = strrpos($string, ' ');
606 View Code Duplication
        if ($pos >= $length - 4) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
607
            $string = substr($string, 0, $length - 4);
608
            $pos    = strrpos($string, ' ');
609
        }
610
        if ($pos >= $length * 0.4) {
611
            return substr($string, 0, $pos) . ' ...';
612
        }
613
614
        return substr($string, 0, $length - 4) . ' ...';
615
    }
616
617
    /**
618
     * Creates a comment indicating the generator of this feed.
619
     * The format of this comment seems to be recognized by
620
     * Syndic8.com.
621
     */
622
    public function _createGeneratorComment()
623
    {
624
        return '<!-- generator="' . FEEDCREATOR_VERSION . "\" -->\n";
625
    }
626
627
    /**
628
     * Creates a string containing all additional elements specified in
629
     * $additionalElements.
630
     * @param array  $elements
631
     * @param string $indentString
632
     * @return string the XML tags corresponding to $additionalElements
633
     * @internal param array $elements an associative array containing key => value pairs
634
     * @internal param string $indentString a string that will be inserted before every generated line
635
     */
636
    public function _createAdditionalElements($elements, $indentString = '')
637
    {
638
        $ae = '';
639
        if (is_array($elements)) {
640
            foreach ($elements as $key => $value) {
641
                $ae .= $indentString . "<$key>$value</$key>\n";
642
            }
643
        }
644
645
        return $ae;
646
    }
647
648
    /**
649
     * @return string
650
     */
651
    public function _createStylesheetReferences()
652
    {
653
        $xml = '';
654
        if ($this->cssStyleSheet) {
655
            $xml .= '<?xml-stylesheet href="' . $this->cssStyleSheet . "\" type=\"text/css\"?>\n";
656
        }
657
        if ($this->xslStyleSheet) {
658
            $xml .= '<?xml-stylesheet href="' . $this->xslStyleSheet . "\" type=\"text/xsl\"?>\n";
659
        }
660
661
        return $xml;
662
    }
663
664
    /**
665
     * Builds the feed's text.
666
     * @abstract
667
     * @return string the feed's complete text
668
     */
669
    public function createFeed()
670
    {
671
    }
672
673
    /**
674
     * Generate a filename for the feed cache file. The result will be $_SERVER["PHP_SELF"] with the extension changed to .xml.
675
     * For example:
676
     *
677
     * echo $_SERVER["PHP_SELF"]."\n";
678
     * echo FeedCreator::_generateFilename();
679
     *
680
     * would produce:
681
     *
682
     * /rss/latestnews.php
683
     * latestnews.xml
684
     *
685
     * @return string the feed cache filename
686
     * @since  1.4
687
     * @access private
688
     */
689
    public function _generateFilename()
690
    {
691
        $fileInfo = pathinfo($_SERVER['PHP_SELF']);
692
693
        return substr($fileInfo['basename'], 0, -(strlen($fileInfo['extension']) + 1)) . '.xml';
694
    }
695
696
    /**
697
     * @since  1.4
698
     * @access private
699
     * @param $filename
700
     */
701
    public function _redirect($filename)
702
    {
703
        // attention, heavily-commented-out-area
704
705
        // maybe use this in addition to file time checking
706
        //Header("Expires: ".date("r",time()+$this->_timeout));
707
708
        /* no caching at all, doesn't seem to work as good:
709
        Header("Cache-Control: no-cache");
710
        Header("Pragma: no-cache");
711
        */
712
713
        // HTTP redirect, some feed readers' simple HTTP implementations don't follow it
714
        //Header("Location: ".$filename);
715
716
        header('Content-Type: ' . $this->contentType . '; charset=' . $this->encoding . '; filename=' . basename($filename));
717
        header('Content-Disposition: inline; filename=' . basename($filename));
718
        readfile($filename, 'r');
719
        die();
720
    }
721
722
    /**
723
     * Turns on caching and checks if there is a recent version of this feed in the cache.
724
     * If there is, an HTTP redirect header is sent.
725
     * To effectively use caching, you should create the FeedCreator object and call this method
726
     * before anything else, especially before you do the time consuming task to build the feed
727
     * (web fetching, for example).
728
     * @since    1.4
729
     * @param     filename  string  optional    the filename where a recent version of the feed is saved. If not specified, the filename is $_SERVER["PHP_SELF"] with the extension changed to .xml (see _generateFilename()).
730
     * @param int $timeout
731
     * @internal param int $timeout optional    the timeout in seconds before a cached version is refreshed (defaults to 3600 = 1 hour)
732
     */
733
    public function useCached($filename = '', $timeout = 3600)
734
    {
735
        $this->_timeout = $timeout;
0 ignored issues
show
Bug introduced by
The property _timeout does not exist. Did you maybe forget to declare it?

In PHP it is possible to write to properties without declaring them. For example, the following is perfectly valid PHP code:

class MyClass { }

$x = new MyClass();
$x->foo = true;

Generally, it is a good practice to explictly declare properties to avoid accidental typos and provide IDE auto-completion:

class MyClass {
    public $foo;
}

$x = new MyClass();
$x->foo = true;
Loading history...
736
        if ('' == $filename) {
737
            $filename = $this->_generateFilename();
738
        }
739
        if (file_exists($filename) && (time() - filemtime($filename) < $timeout)) {
740
            $this->_redirect($filename);
741
        }
742
    }
743
744
    /**
745
     * Saves this feed as a file on the local disk. After the file is saved, a redirect
746
     * header may be sent to redirect the user to the newly created file.
747
     * @since    1.4
748
     *
749
     * @param      filename  string  optional    the filename where a recent version of the feed is saved. If not specified, the filename is $_SERVER["PHP_SELF"] with the extension changed to .xml (see _generateFilename()).
750
     * @param bool $displayContents
751
     * @internal param bool $redirect optional    send an HTTP redirect header or not. If true, the user will be automatically redirected to the created file.
752
     */
753
    public function saveFeed($filename = '', $displayContents = true)
754
    {
755
        if ('' == $filename) {
756
            $filename = $this->_generateFilename();
757
        }
758
        $feedFile = fopen($filename, 'w+');
759
        if ($feedFile) {
760
            fwrite($feedFile, $this->createFeed());
761
            fclose($feedFile);
762
            if ($displayContents) {
763
                $this->_redirect($filename);
764
            }
765
        } else {
766
            echo '<br><b>Error creating feed file, please check write permissions.</b><br>';
767
        }
768
    }
769
}
770
771
/**
772
 * FeedDate is an internal class that stores a date for a feed or feed item.
773
 * Usually, you won't need to use this.
774
 */
775
class FeedDate
776
{
777
    public $unix;
778
779
    /**
780
     * Creates a new instance of FeedDate representing a given date.
781
     * Accepts RFC 822, ISO 8601 date formats as well as unix time stamps.
782
     * @param mixed $dateString optional the date this FeedDate will represent. If not specified, the current date and time is used.
783
     */
784
    public function __construct($dateString = '')
785
    {
786
        $tzOffset = 0;
787
        if ('' == $dateString) {
788
            $dateString = date('r');
789
        }
790
791
        //if (is_integer($dateString)) {
792
        if (is_numeric($dateString)) {
793
            $this->unix = $dateString;
794
795
            return;
796
        }
797
        if (preg_match("~(?:(?:Mon|Tue|Wed|Thu|Fri|Sat|Sun),\\s+)?(\\d{1,2})\\s+([a-zA-Z]{3})\\s+(\\d{4})\\s+(\\d{2}):(\\d{2}):(\\d{2})\\s+(.*)~", $dateString, $matches)) {
798
            $months     = [
799
                'Jan' => 1,
800
                'Feb' => 2,
801
                'Mar' => 3,
802
                'Apr' => 4,
803
                'May' => 5,
804
                'Jun' => 6,
805
                'Jul' => 7,
806
                'Aug' => 8,
807
                'Sep' => 9,
808
                'Oct' => 10,
809
                'Nov' => 11,
810
                'Dec' => 12
811
            ];
812
            $this->unix = mktime($matches[4], $matches[5], $matches[6], $months[$matches[2]], $matches[1], $matches[3]);
813
            if ('+' == substr($matches[7], 0, 1) || '-' == substr($matches[7], 0, 1)) {
814
                $tzOffset = (substr($matches[7], 0, 3) * 60 + substr($matches[7], -2)) * 60;
815
            } else {
816
                if (1 == strlen($matches[7])) {
817
                    $oneHour = 3600;
818
                    $ord     = ord($matches[7]);
819
                    if ($ord < ord('M')) {
820
                        $tzOffset = (ord('A') - $ord - 1) * $oneHour;
821
                    } elseif ($ord >= ord('M') && 'Z' !== $matches[7]) {
822
                        $tzOffset = ($ord - ord('M')) * $oneHour;
823
                    } elseif ('Z' === $matches[7]) {
824
                        $tzOffset = 0;
825
                    }
826
                }
827
                switch ($matches[7]) {
828
                    case 'UT':
829
                    case 'GMT':
830
                        $tzOffset = 0;
831
                }
832
            }
833
            $this->unix += $tzOffset;
834
835
            return;
836
        }
837
        if (preg_match("~(\\d{4})-(\\d{2})-(\\d{2})T(\\d{2}):(\\d{2}):(\\d{2})(.*)~", $dateString, $matches)) {
838
            $this->unix = mktime($matches[4], $matches[5], $matches[6], $matches[2], $matches[3], $matches[1]);
839
            if ('+' == substr($matches[7], 0, 1) || '-' == substr($matches[7], 0, 1)) {
840
                $tzOffset = (substr($matches[7], 0, 3) * 60 + substr($matches[7], -2)) * 60;
841
            } else {
842
                if ('Z' === $matches[7]) {
843
                    $tzOffset = 0;
844
                }
845
            }
846
            $this->unix += $tzOffset;
847
848
            return;
849
        }
850
        $this->unix = 0;
851
    }
852
853
    /**
854
     * Gets the date stored in this FeedDate as an RFC 822 date.
855
     *
856
     * @return a date in RFC 822 format
857
     */
858
    public function rfc822()
859
    {
860
        //return gmdate("r",$this->unix);
861
        $date = gmdate('D, d M Y H:i:s', $this->unix);
862
        if (TIME_ZONE != '') {
863
            $date .= ' ' . str_replace(':', '', TIME_ZONE);
864
        }
865
866
        return $date;
867
    }
868
869
    /**
870
     * Gets the date stored in this FeedDate as an ISO 8601 date.
871
     *
872
     * @return a date in ISO 8601 format
873
     */
874
    public function iso8601()
875
    {
876
        $date = gmdate("Y-m-d\TH:i:sO", $this->unix);
877
        $date = substr($date, 0, 22) . ':' . substr($date, -2);
878
        if (TIME_ZONE != '') {
879
            $date = str_replace('+00:00', TIME_ZONE, $date);
880
        }
881
882
        return $date;
883
    }
884
885
    /**
886
     * Gets the date stored in this FeedDate as unix time stamp.
887
     *
888
     * @return a date as a unix time stamp
889
     */
890
    public function unix()
891
    {
892
        return $this->unix;
893
    }
894
}
895
896
/**
897
 * RSSCreator10 is a FeedCreator that implements RDF Site Summary (RSS) 1.0.
898
 *
899
 * @see    http://www.purl.org/rss/1.0/
900
 * @since  1.3
901
 * @author Kai Blankenhorn <[email protected]>
902
 */
903
class RSSCreator10 extends FeedCreator
904
{
905
    /**
906
     * Builds the RSS feed's text. The feed will be compliant to RDF Site Summary (RSS) 1.0.
907
     * The feed will contain all items previously added in the same order.
908
     * @return string the feed's complete text
909
     */
910
    public function createFeed()
911
    {
912
        $feed = '<?xml version="1.0" encoding="' . $this->encoding . "\"?>\n";
913
        $feed .= $this->_createGeneratorComment();
914
        if ('' == $this->cssStyleSheet) {
915
            $cssStyleSheet = 'http://www.w3.org/2000/08/w3c-synd/style.css';
0 ignored issues
show
Unused Code introduced by
$cssStyleSheet is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
916
        }
917
        $feed .= $this->_createStylesheetReferences();
918
        $feed .= "<rdf:RDF\n";
919
        $feed .= "    xmlns=\"http://purl.org/rss/1.0/\"\n";
920
        $feed .= "    xmlns:rdf=\"http://www.w3.org/1999/02/22-rdf-syntax-ns#\"\n";
921
        $feed .= "    xmlns:slash=\"http://purl.org/rss/1.0/modules/slash/\"\n";
922
        $feed .= "    xmlns:dc=\"http://purl.org/dc/elements/1.1/\">\n";
923
        $feed .= '    <channel rdf:about="' . $this->syndicationURL . "\">\n";
924
        $feed .= '        <title>' . htmlspecialchars($this->title, ENT_QUOTES | ENT_HTML5) . "</title>\n";
925
        $feed .= '        <description>' . htmlspecialchars($this->description, ENT_QUOTES | ENT_HTML5) . "</description>\n";
926
        $feed .= '        <link>' . $this->link . "</link>\n";
927
        if (null != $this->image) {
928
            $feed .= '        <image rdf:resource="' . $this->image->url . "\">\n";
929
        }
930
        $now  = new FeedDate();
931
        $feed .= '       <dc:date>' . htmlspecialchars($now->iso8601(), ENT_QUOTES | ENT_HTML5) . "</dc:date>\n";
932
        $feed .= "        <items>\n";
933
        $feed .= "            <rdf:Seq>\n";
934
        for ($i = 0, $iMax = count($this->items); $i < $iMax; ++$i) {
935
            $feed .= '                <rdf:li rdf:resource="' . htmlspecialchars($this->items[$i]->link, ENT_QUOTES | ENT_HTML5) . "\">\n";
936
        }
937
        $feed .= "            </rdf:Seq>\n";
938
        $feed .= "        </items>\n";
939
        $feed .= "    </channel>\n";
940
        if (null != $this->image) {
941
            $feed .= '    <image rdf:about="' . $this->image->url . "\">\n";
942
            $feed .= '        <title>' . $this->image->title . "</title>\n";
943
            $feed .= '        <link>' . $this->image->link . "</link>\n";
944
            $feed .= '        <url>' . $this->image->url . "</url>\n";
945
            $feed .= "    </image>\n";
946
        }
947
        $feed .= $this->_createAdditionalElements($this->additionalElements, '    ');
948
949
        for ($i = 0, $iMax = count($this->items); $i < $iMax; ++$i) {
950
            $feed .= '    <item rdf:about="' . htmlspecialchars($this->items[$i]->link, ENT_QUOTES | ENT_HTML5) . "\">\n";
951
            //$feed.= "        <dc:type>Posting</dc:type>\n";
952
            $feed .= "        <dc:format>text/html</dc:format>\n";
953 View Code Duplication
            if (null != $this->items[$i]->date) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
954
                $itemDate = new FeedDate($this->items[$i]->date);
955
                $feed     .= '        <dc:date>' . htmlspecialchars($itemDate->iso8601(), ENT_QUOTES | ENT_HTML5) . "</dc:date>\n";
956
            }
957
            if ('' != $this->items[$i]->source) {
958
                $feed .= '        <dc:source>' . htmlspecialchars($this->items[$i]->source, ENT_QUOTES | ENT_HTML5) . "</dc:source>\n";
959
            }
960
            if ('' != $this->items[$i]->author) {
961
                $feed .= '        <dc:creator>' . htmlspecialchars($this->items[$i]->author, ENT_QUOTES | ENT_HTML5) . "</dc:creator>\n";
962
            }
963
            $feed .= '        <title>' . htmlspecialchars(strip_tags(strtr($this->items[$i]->title, "\n\r", '  ')), ENT_QUOTES | ENT_HTML5) . "</title>\n";
964
            $feed .= '        <link>' . htmlspecialchars($this->items[$i]->link, ENT_QUOTES | ENT_HTML5) . "</link>\n";
965
            $feed .= '        <description>' . htmlspecialchars($this->items[$i]->description, ENT_QUOTES | ENT_HTML5) . "</description>\n";
966
            $feed .= $this->_createAdditionalElements($this->items[$i]->additionalElements, '        ');
967
            $feed .= "    </item>\n";
968
        }
969
        $feed .= "</rdf:RDF>\n";
970
971
        return $feed;
972
    }
973
}
974
975
/**
976
 * RSSCreator091 is a FeedCreator that implements RSS 0.91 Spec, revision 3.
977
 *
978
 * @see    http://my.netscape.com/publish/formats/rss-spec-0.91.html
979
 * @since  1.3
980
 * @author Kai Blankenhorn <[email protected]>
981
 */
982
class RSSCreator091 extends FeedCreator
983
{
984
    /**
985
     * Stores this RSS feed's version number.
986
     * @access private
987
     */
988
    public $RSSVersion;
989
990
    /**
991
     * RSSCreator091 constructor.
992
     */
993
    public function __construct()
994
    {
995
        $this->_setRSSVersion('0.91');
996
        $this->contentType = 'application/rss+xml';
997
    }
998
999
    /**
1000
     * Sets this RSS feed's version number.
1001
     * @access private
1002
     * @param $version
1003
     */
1004
    public function _setRSSVersion($version)
1005
    {
1006
        $this->RSSVersion = $version;
1007
    }
1008
1009
    /**
1010
     * Builds the RSS feed's text. The feed will be compliant to RDF Site Summary (RSS) 1.0.
1011
     * The feed will contain all items previously added in the same order.
1012
     * @return string the feed's complete text
1013
     */
1014
    public function createFeed()
1015
    {
1016
        $feed                       = '<?xml version="1.0" encoding="' . $this->encoding . "\"?>\n";
1017
        $feed                       .= $this->_createGeneratorComment();
1018
        $feed                       .= $this->_createStylesheetReferences();
1019
        $feed                       .= '<rss version="' . $this->RSSVersion . "\">\n";
1020
        $feed                       .= "    <channel>\n";
1021
        $feed                       .= '        <title>' . FeedCreator::iTrunc(htmlspecialchars($this->title, ENT_QUOTES | ENT_HTML5), 100) . "</title>\n";
1022
        $this->descriptionTruncSize = 500;
1023
        $feed                       .= '        <description>' . $this->getDescription() . "</description>\n";
1024
        $feed                       .= '        <link>' . $this->link . "</link>\n";
1025
        $now                        = new FeedDate();
1026
        $feed                       .= '        <lastBuildDate>' . htmlspecialchars($now->rfc822(), ENT_QUOTES | ENT_HTML5) . "</lastBuildDate>\n";
1027
        $feed                       .= '        <generator>' . FEEDCREATOR_VERSION . "</generator>\n";
1028
1029
        if (null != $this->image) {
1030
            $feed .= "        <image>\n";
1031
            $feed .= '            <url>' . $this->image->url . "</url>\n";
1032
            $feed .= '            <title>' . FeedCreator::iTrunc(htmlspecialchars($this->image->title, ENT_QUOTES | ENT_HTML5), 100) . "</title>\n";
1033
            $feed .= '            <link>' . $this->image->link . "</link>\n";
1034
            if ('' != $this->image->width) {
1035
                $feed .= '            <width>' . $this->image->width . "</width>\n";
1036
            }
1037
            if ('' != $this->image->height) {
1038
                $feed .= '            <height>' . $this->image->height . "</height>\n";
1039
            }
1040
            if ('' != $this->image->description) {
1041
                $feed .= '            <description>' . $this->image->getDescription() . "</description>\n";
1042
            }
1043
            $feed .= "        </image>\n";
1044
        }
1045
        if ('' != $this->language) {
1046
            $feed .= '        <language>' . $this->language . "</language>\n";
1047
        }
1048 View Code Duplication
        if ('' != $this->copyright) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
1049
            $feed .= '        <copyright>' . FeedCreator::iTrunc(htmlspecialchars($this->copyright, ENT_QUOTES | ENT_HTML5), 100) . "</copyright>\n";
1050
        }
1051 View Code Duplication
        if ('' != $this->editor) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
1052
            $feed .= '        <managingEditor>' . FeedCreator::iTrunc(htmlspecialchars($this->editor, ENT_QUOTES | ENT_HTML5), 100) . "</managingEditor>\n";
1053
        }
1054 View Code Duplication
        if ('' != $this->webmaster) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
1055
            $feed .= '        <webMaster>' . FeedCreator::iTrunc(htmlspecialchars($this->webmaster, ENT_QUOTES | ENT_HTML5), 100) . "</webMaster>\n";
1056
        }
1057
        if ('' != $this->pubDate) {
1058
            $pubDate = new FeedDate($this->pubDate);
1059
            $feed    .= '        <pubDate>' . htmlspecialchars($pubDate->rfc822(), ENT_QUOTES | ENT_HTML5) . "</pubDate>\n";
1060
        }
1061
        if ('' != $this->category) {
1062
            $feed .= '        <category>' . htmlspecialchars($this->category, ENT_QUOTES | ENT_HTML5) . "</category>\n";
1063
        }
1064 View Code Duplication
        if ('' != $this->docs) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
1065
            $feed .= '        <docs>' . FeedCreator::iTrunc(htmlspecialchars($this->docs, ENT_QUOTES | ENT_HTML5), 500) . "</docs>\n";
1066
        }
1067 View Code Duplication
        if ('' != $this->ttl) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
1068
            $feed .= '        <ttl>' . htmlspecialchars($this->ttl, ENT_QUOTES | ENT_HTML5) . "</ttl>\n";
1069
        }
1070 View Code Duplication
        if ('' != $this->rating) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
1071
            $feed .= '        <rating>' . FeedCreator::iTrunc(htmlspecialchars($this->rating, ENT_QUOTES | ENT_HTML5), 500) . "</rating>\n";
1072
        }
1073
        if ('' != $this->skipHours) {
1074
            $feed .= '        <skipHours>' . htmlspecialchars($this->skipHours, ENT_QUOTES | ENT_HTML5) . "</skipHours>\n";
1075
        }
1076 View Code Duplication
        if ('' != $this->skipDays) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
1077
            $feed .= '        <skipDays>' . htmlspecialchars($this->skipDays, ENT_QUOTES | ENT_HTML5) . "</skipDays>\n";
1078
        }
1079
        $feed .= $this->_createAdditionalElements($this->additionalElements, '    ');
1080
1081
        for ($i = 0, $iMax = count($this->items); $i < $iMax; ++$i) {
1082
            $feed .= "        <item>\n";
1083
            $feed .= '            <title>' . FeedCreator::iTrunc(htmlspecialchars(strip_tags($this->items[$i]->title), ENT_QUOTES | ENT_HTML5), 100) . "</title>\n";
1084
            $feed .= '            <link>' . htmlspecialchars($this->items[$i]->link, ENT_QUOTES | ENT_HTML5) . "</link>\n";
1085
            $feed .= '            <description>' . $this->items[$i]->getDescription() . "</description>\n";
1086
1087
            if ('' != $this->items[$i]->author) {
1088
                $feed .= '            <author>' . htmlspecialchars($this->items[$i]->author, ENT_QUOTES | ENT_HTML5) . "</author>\n";
1089
            }
1090
            /*
1091
            // on hold
1092
            if ($this->items[$i]->source!="") {
1093
                    $feed.= "            <source>".htmlspecialchars($this->items[$i]->source)."</source>\n";
1094
            }
1095
            */
1096
            if ('' != $this->items[$i]->category) {
1097
                $feed .= '            <category>' . htmlspecialchars($this->items[$i]->category, ENT_QUOTES | ENT_HTML5) . "</category>\n";
1098
            }
1099
            if ('' != $this->items[$i]->comments) {
1100
                $feed .= '            <comments>' . htmlspecialchars($this->items[$i]->comments, ENT_QUOTES | ENT_HTML5) . "</comments>\n";
1101
            }
1102 View Code Duplication
            if ('' != $this->items[$i]->date) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
1103
                $itemDate = new FeedDate($this->items[$i]->date);
1104
                $feed     .= '            <pubDate>' . htmlspecialchars($itemDate->rfc822(), ENT_QUOTES | ENT_HTML5) . "</pubDate>\n";
1105
            }
1106
            if ('' != $this->items[$i]->guid) {
1107
                $feed .= '            <guid>' . htmlspecialchars($this->items[$i]->guid, ENT_QUOTES | ENT_HTML5) . "</guid>\n";
1108
            }
1109
            $feed .= $this->_createAdditionalElements($this->items[$i]->additionalElements, '        ');
1110
            $feed .= "        </item>\n";
1111
        }
1112
        $feed .= "    </channel>\n";
1113
        $feed .= "</rss>\n";
1114
1115
        return $feed;
1116
    }
1117
}
1118
1119
/**
1120
 * RSSCreator20 is a FeedCreator that implements RDF Site Summary (RSS) 2.0.
1121
 *
1122
 * @see    http://backend.userland.com/rss
1123
 * @since  1.3
1124
 * @author Kai Blankenhorn <[email protected]>
1125
 */
1126
class RSSCreator20 extends RSSCreator091
1127
{
1128
    /**
1129
     * RSSCreator20 constructor.
1130
     */
1131
    public function __construct()
1132
    {
1133
        parent::_setRSSVersion('2.0');
0 ignored issues
show
Comprehensibility Bug introduced by
It seems like you call parent on a different method (_setRSSVersion() instead of __construct()). Are you sure this is correct? If so, you might want to change this to $this->_setRSSVersion().

This check looks for a call to a parent method whose name is different than the method from which it is called.

Consider the following code:

class Daddy
{
    protected function getFirstName()
    {
        return "Eidur";
    }

    protected function getSurName()
    {
        return "Gudjohnsen";
    }
}

class Son
{
    public function getFirstName()
    {
        return parent::getSurname();
    }
}

The getFirstName() method in the Son calls the wrong method in the parent class.

Loading history...
1134
    }
1135
}
1136
1137
/**
1138
 * PIECreator01 is a FeedCreator that implements the emerging PIE specification,
1139
 * as in http://intertwingly.net/wiki/pie/Syntax.
1140
 *
1141
 * @deprecated
1142
 * @since  1.3
1143
 * @author Scott Reynen <[email protected]> and Kai Blankenhorn <[email protected]>
1144
 */
1145
class PIECreator01 extends FeedCreator
1146
{
1147
    /**
1148
     * PIECreator01 constructor.
1149
     */
1150
    public function __construct()
1151
    {
1152
        $this->encoding = 'utf-8';
1153
    }
1154
1155
    /**
1156
     * @return string
1157
     */
1158
    public function createFeed()
1159
    {
1160
        $feed            = '<?xml version="1.0" encoding="' . $this->encoding . "\"?>\n";
1161
        $feed            .= $this->_createStylesheetReferences();
1162
        $feed            .= "<feed version=\"0.1\" xmlns=\"http://example.com/newformat#\">\n";
1163
        $feed            .= '    <title>' . FeedCreator::iTrunc(htmlspecialchars($this->title, ENT_QUOTES | ENT_HTML5), 100) . "</title>\n";
1164
        $this->truncSize = 500;
0 ignored issues
show
Bug introduced by
The property truncSize does not seem to exist. Did you mean descriptionTruncSize?

An attempt at access to an undefined property has been detected. This may either be a typographical error or the property has been renamed but there are still references to its old name.

If you really want to allow access to undefined properties, you can define magic methods to allow access. See the php core documentation on Overloading.

Loading history...
1165
        $feed            .= '    <subtitle>' . $this->getDescription() . "</subtitle>\n";
1166
        $feed            .= '    <link>' . $this->link . "</link>\n";
1167
        for ($i = 0, $iMax = count($this->items); $i < $iMax; ++$i) {
1168
            $feed     .= "    <entry>\n";
1169
            $feed     .= '        <title>' . FeedCreator::iTrunc(htmlspecialchars(strip_tags($this->items[$i]->title), ENT_QUOTES | ENT_HTML5), 100) . "</title>\n";
1170
            $feed     .= '        <link>' . htmlspecialchars($this->items[$i]->link, ENT_QUOTES | ENT_HTML5) . "</link>\n";
1171
            $itemDate = new FeedDate($this->items[$i]->date);
1172
            $feed     .= '        <created>' . htmlspecialchars($itemDate->iso8601(), ENT_QUOTES | ENT_HTML5) . "</created>\n";
1173
            $feed     .= '        <issued>' . htmlspecialchars($itemDate->iso8601(), ENT_QUOTES | ENT_HTML5) . "</issued>\n";
1174
            $feed     .= '        <modified>' . htmlspecialchars($itemDate->iso8601(), ENT_QUOTES | ENT_HTML5) . "</modified>\n";
1175
            $feed     .= '        <id>' . htmlspecialchars($this->items[$i]->guid, ENT_QUOTES | ENT_HTML5) . "</id>\n";
1176
            if ('' != $this->items[$i]->author) {
1177
                $feed .= "        <author>\n";
1178
                $feed .= '            <name>' . htmlspecialchars($this->items[$i]->author, ENT_QUOTES | ENT_HTML5) . "</name>\n";
1179
                if ('' != $this->items[$i]->authorEmail) {
1180
                    $feed .= '            <email>' . $this->items[$i]->authorEmail . "</email>\n";
1181
                }
1182
                $feed .= "        </author>\n";
1183
            }
1184
            $feed .= "        <content type=\"text/html\" xml:lang=\"en-us\">\n";
1185
            $feed .= '            <div xmlns="http://www.w3.org/1999/xhtml">' . $this->items[$i]->getDescription() . "</div>\n";
1186
            $feed .= "        </content>\n";
1187
            $feed .= "    </entry>\n";
1188
        }
1189
        $feed .= "</feed>\n";
1190
1191
        return $feed;
1192
    }
1193
}
1194
1195
/**
1196
 * AtomCreator03 is a FeedCreator that implements the atom specification,
1197
 * as in http://www.intertwingly.net/wiki/pie/FrontPage.
1198
 * Please note that just by using AtomCreator03 you won't automatically
1199
 * produce valid atom files. For example, you have to specify either an editor
1200
 * for the feed or an author for every single feed item.
1201
 *
1202
 * Some elements have not been implemented yet. These are (incomplete list):
1203
 * author URL, item author's email and URL, item contents, alternate links,
1204
 * other link content types than text/html. Some of them may be created with
1205
 * AtomCreator03::additionalElements.
1206
 *
1207
 * @see    FeedCreator#additionalElements
1208
 * @since  1.6
1209
 * @author Kai Blankenhorn <[email protected]>, Scott Reynen <[email protected]>
1210
 */
1211
class AtomCreator03 extends FeedCreator
1212
{
1213
    /**
1214
     * AtomCreator03 constructor.
1215
     */
1216
    public function __construct()
1217
    {
1218
        $this->contentType = 'application/atom+xml';
1219
        $this->encoding    = 'utf-8';
1220
    }
1221
1222
    /**
1223
     * @return string
1224
     */
1225
    public function createFeed()
1226
    {
1227
        $feed = '<?xml version="1.0" encoding="' . $this->encoding . "\"?>\n";
1228
        $feed .= $this->_createGeneratorComment();
1229
        $feed .= $this->_createStylesheetReferences();
1230
        $feed .= '<feed version="0.3" xmlns="http://purl.org/atom/ns#"';
1231
        if ('' != $this->language) {
1232
            $feed .= ' xml:lang="' . $this->language . '"';
1233
        }
1234
        $feed .= ">\n";
1235
        $feed .= '    <title>' . htmlspecialchars($this->title, ENT_QUOTES | ENT_HTML5) . "</title>\n";
1236
        $feed .= '    <tagline>' . htmlspecialchars($this->description, ENT_QUOTES | ENT_HTML5) . "</tagline>\n";
1237
        $feed .= '    <link rel="alternate" type="text/html" href="' . htmlspecialchars($this->link, ENT_QUOTES | ENT_HTML5) . "\">\n";
1238
        $feed .= '    <id>' . htmlspecialchars($this->link, ENT_QUOTES | ENT_HTML5) . "</id>\n";
1239
        $now  = new FeedDate();
1240
        $feed .= '    <modified>' . htmlspecialchars($now->iso8601(), ENT_QUOTES | ENT_HTML5) . "</modified>\n";
1241
        if ('' != $this->editor) {
1242
            $feed .= "    <author>\n";
1243
            $feed .= '        <name>' . $this->editor . "</name>\n";
1244
            if ('' != $this->editorEmail) {
1245
                $feed .= '        <email>' . $this->editorEmail . "</email>\n";
1246
            }
1247
            $feed .= "    </author>\n";
1248
        }
1249
        $feed .= '    <generator>' . FEEDCREATOR_VERSION . "</generator>\n";
1250
        $feed .= $this->_createAdditionalElements($this->additionalElements, '    ');
1251
        for ($i = 0, $iMax = count($this->items); $i < $iMax; ++$i) {
1252
            $feed .= "    <entry>\n";
1253
            $feed .= '        <title>' . htmlspecialchars(strip_tags($this->items[$i]->title), ENT_QUOTES | ENT_HTML5) . "</title>\n";
1254
            $feed .= '        <link rel="alternate" type="text/html" href="' . htmlspecialchars($this->items[$i]->link, ENT_QUOTES | ENT_HTML5) . "\">\n";
1255
            if ('' == $this->items[$i]->date) {
1256
                $this->items[$i]->date = time();
1257
            }
1258
            $itemDate = new FeedDate($this->items[$i]->date);
1259
            $feed     .= '        <created>' . htmlspecialchars($itemDate->iso8601(), ENT_QUOTES | ENT_HTML5) . "</created>\n";
1260
            $feed     .= '        <issued>' . htmlspecialchars($itemDate->iso8601(), ENT_QUOTES | ENT_HTML5) . "</issued>\n";
1261
            $feed     .= '        <modified>' . htmlspecialchars($itemDate->iso8601(), ENT_QUOTES | ENT_HTML5) . "</modified>\n";
1262
            $feed     .= '        <id>' . htmlspecialchars($this->items[$i]->link, ENT_QUOTES | ENT_HTML5) . "</id>\n";
1263
            $feed     .= $this->_createAdditionalElements($this->items[$i]->additionalElements, '        ');
1264
            if ('' != $this->items[$i]->author) {
1265
                $feed .= "        <author>\n";
1266
                $feed .= '            <name>' . htmlspecialchars($this->items[$i]->author, ENT_QUOTES | ENT_HTML5) . "</name>\n";
1267
                $feed .= "        </author>\n";
1268
            }
1269
            if ('' != $this->items[$i]->description) {
1270
                $feed .= '        <summary>' . htmlspecialchars($this->items[$i]->description, ENT_QUOTES | ENT_HTML5) . "</summary>\n";
1271
            }
1272
            $feed .= "    </entry>\n";
1273
        }
1274
        $feed .= "</feed>\n";
1275
1276
        return $feed;
1277
    }
1278
}
1279
1280
/**
1281
 * MBOXCreator is a FeedCreator that implements the mbox format
1282
 * as described in http://www.qmail.org/man/man5/mbox.html
1283
 *
1284
 * @since  1.3
1285
 * @author Kai Blankenhorn <[email protected]>
1286
 */
1287
class MBOXCreator extends FeedCreator
1288
{
1289
    /**
1290
     * MBOXCreator constructor.
1291
     */
1292
    public function __construct()
1293
    {
1294
        $this->contentType = 'text/plain';
1295
        $this->encoding    = 'ISO-8859-15';
1296
    }
1297
1298
    /**
1299
     * @param string $input
1300
     * @param int    $line_max
1301
     * @return string
1302
     */
1303
    public function qp_enc($input = '', $line_max = 76)
1304
    {
1305
        $hex    = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'];
1306
        $lines  = preg_split("/(?:\r\n|\r|\n)/", $input);
1307
        $eol    = "\r\n";
1308
        $escape = '=';
1309
        $output = '';
1310
        //        while (list(, $line) = each($lines)) {
1311
        foreach ($lines as $key => $line) {
1312
            //$line = rtrim($line); // remove trailing white space -> no =20\r\n necessary
1313
            $linlen  = strlen($line);
1314
            $newline = '';
1315
            for ($i = 0; $i < $linlen; ++$i) {
1316
                $c   = substr($line, $i, 1);
1317
                $dec = ord($c);
1318
                if ((32 == $dec) && ($i == ($linlen - 1))) { // convert space at eol only
1319
                    $c = '=20';
1320
                } elseif ((61 == $dec) || ($dec < 32) || ($dec > 126)) { // always encode "\t", which is *not* required
1321
                    $h2 = floor($dec / 16);
1322
                    $h1 = floor($dec % 16);
1323
                    $c  = $escape . $hex[(string)$h2] . $hex[(string)$h1];
1324
                }
1325
                if ((strlen($newline) + strlen($c)) >= $line_max) { // CRLF is not counted
1326
                    $output  .= $newline . $escape . $eol; // soft line break; " =\r\n" is okay
1327
                    $newline = '';
1328
                }
1329
                $newline .= $c;
1330
            } // end of for
1331
            $output .= $newline . $eol;
1332
        }
1333
1334
        return trim($output);
1335
    }
1336
1337
    /**
1338
     * Builds the MBOX contents.
1339
     * @return string the feed's complete text
1340
     */
1341
    public function createFeed()
1342
    {
1343
        for ($i = 0, $iMax = count($this->items); $i < $iMax; ++$i) {
1344
            if ('' != $this->items[$i]->author) {
1345
                $from = $this->items[$i]->author;
1346
            } else {
1347
                $from = $this->title;
1348
            }
1349
            $itemDate = new FeedDate($this->items[$i]->date);
1350
            $feed     .= 'From ' . strtr(self::qp_enc($from), ' ', '_') . ' ' . date('D M d H:i:s Y', $itemDate->unix()) . "\n";
0 ignored issues
show
Bug introduced by
The variable $feed does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
1351
            $feed     .= "Content-Type: text/plain;\n";
1352
            $feed     .= '   charset="' . $this->encoding . "\"\n";
1353
            $feed     .= "Content-Transfer-Encoding: quoted-printable\n";
1354
            $feed     .= "Content-Type: text/plain\n";
1355
            $feed     .= 'From: "' . self::qp_enc($from) . "\"\n";
1356
            $feed     .= 'Date: ' . $itemDate->rfc822() . "\n";
1357
            $feed     .= 'Subject: ' . self::qp_enc(FeedCreator::iTrunc($this->items[$i]->title, 100)) . "\n";
1358
            $feed     .= "\n";
1359
            $body     = chunk_split(self::qp_enc($this->items[$i]->description));
1360
            $feed     .= preg_replace("~\nFrom ([^\n]*)(\n?)~", "\n>From $1$2\n", $body);
1361
            $feed     .= "\n";
1362
            $feed     .= "\n";
1363
        }
1364
1365
        return $feed;
1366
    }
1367
1368
    /**
1369
     * Generate a filename for the feed cache file. Overridden from FeedCreator to prevent XML data types.
1370
     * @return string the feed cache filename
1371
     * @since  1.4
1372
     * @access private
1373
     */
1374
    public function _generateFilename()
1375
    {
1376
        $fileInfo = pathinfo($_SERVER['PHP_SELF']);
1377
1378
        return substr($fileInfo['basename'], 0, -(strlen($fileInfo['extension']) + 1)) . '.mbox';
1379
    }
1380
}
1381
1382
/**
1383
 * OPMLCreator is a FeedCreator that implements OPML 1.0.
1384
 *
1385
 * @see    http://opml.scripting.com/spec
1386
 * @author Dirk Clemens, Kai Blankenhorn
1387
 * @since  1.5
1388
 */
1389
class OPMLCreator extends FeedCreator
1390
{
1391
    /**
1392
     * OPMLCreator constructor.
1393
     */
1394
    public function __construct()
1395
    {
1396
        $this->encoding = 'utf-8';
1397
    }
1398
1399
    /**
1400
     * @return string
1401
     */
1402
    public function createFeed()
1403
    {
1404
        $feed = '<?xml version="1.0" encoding="' . $this->encoding . "\"?>\n";
1405
        $feed .= $this->_createGeneratorComment();
1406
        $feed .= $this->_createStylesheetReferences();
1407
        $feed .= "<opml xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\">\n";
1408
        $feed .= "    <head>\n";
1409
        $feed .= '        <title>' . htmlspecialchars($this->title, ENT_QUOTES | ENT_HTML5) . "</title>\n";
1410
        if ('' != $this->pubDate) {
1411
            $date = new FeedDate($this->pubDate);
1412
            $feed .= '         <dateCreated>' . $date->rfc822() . "</dateCreated>\n";
1413
        }
1414
        if ('' != $this->lastBuildDate) {
1415
            $date = new FeedDate($this->lastBuildDate);
1416
            $feed .= '         <dateModified>' . $date->rfc822() . "</dateModified>\n";
1417
        }
1418
        if ('' != $this->editor) {
1419
            $feed .= '         <ownerName>' . $this->editor . "</ownerName>\n";
1420
        }
1421
        if ('' != $this->editorEmail) {
1422
            $feed .= '         <ownerEmail>' . $this->editorEmail . "</ownerEmail>\n";
1423
        }
1424
        $feed .= "    </head>\n";
1425
        $feed .= "    <body>\n";
1426
        for ($i = 0, $iMax = count($this->items); $i < $iMax; ++$i) {
1427
            $feed  .= '    <outline type="rss" ';
1428
            $title = htmlspecialchars(strip_tags(strtr($this->items[$i]->title, "\n\r", '  ')), ENT_QUOTES | ENT_HTML5);
1429
            $feed  .= ' title="' . $title . '"';
1430
            $feed  .= ' text="' . $title . '"';
1431
            //$feed.= " description=\"".htmlspecialchars($this->items[$i]->description)."\"";
1432
            $feed .= ' url="' . htmlspecialchars($this->items[$i]->link, ENT_QUOTES | ENT_HTML5) . '"';
1433
            $feed .= ">\n";
1434
        }
1435
        $feed .= "    </body>\n";
1436
        $feed .= "</opml>\n";
1437
1438
        return $feed;
1439
    }
1440
}
1441
1442
/**
1443
 * HTMLCreator is a FeedCreator that writes an HTML feed file to a specific
1444
 * location, overriding the createFeed method of the parent FeedCreator.
1445
 * The HTML produced can be included over http by scripting languages, or serve
1446
 * as the source for an IFrame.
1447
 * All output by this class is embedded in <div></div> tags to enable formatting
1448
 * using CSS.
1449
 *
1450
 * @author Pascal Van Hecke
1451
 * @since  1.7
1452
 */
1453
class HTMLCreator extends FeedCreator
1454
{
1455
    //    public $contentType = 'text/html';
1456
1457
    /**
1458
     * Contains HTML to be output at the start of the feed's html representation.
1459
     */
1460
    public $header;
1461
1462
    /**
1463
     * Contains HTML to be output at the end of the feed's html representation.
1464
     */
1465
    public $footer;
1466
1467
    /**
1468
     * Contains HTML to be output between entries. A separator is only used in
1469
     * case of multiple entries.
1470
     */
1471
    public $separator;
1472
1473
    /**
1474
     * Used to prefix the stylenames to make sure they are unique
1475
     * and do not clash with stylenames on the users' page.
1476
     */
1477
    public $stylePrefix;
1478
1479
    /**
1480
     * Determines whether the links open in a new window or not.
1481
     */
1482
    public $openInNewWindow = true;
1483
1484
    public $imageAlign = 'right';
1485
1486
    /**
1487
     * In case of very simple output you may want to get rid of the style tags,
1488
     * hence this variable.  There's no equivalent on item level, but of course you can
1489
     * add strings to it while iterating over the items ($this->stylelessOutput .= ...)
1490
     * and when it is non-empty, ONLY the styleless output is printed, the rest is ignored
1491
     * in the function createFeed().
1492
     */
1493
    public $stylelessOutput = '';
1494
1495
    /**
1496
     * HTMLCreator constructor.
1497
     */
1498
    public function __construct()
1499
    {
1500
        $this->contentType = 'text/html';
1501
    }
1502
1503
    /**
1504
     * Writes the HTML.
1505
     * @return string the scripts's complete text
1506
     */
1507
    public function createFeed()
1508
    {
1509
        // if there is styleless output, use the content of this variable and ignore the rest
1510
        if ('' != $this->stylelessOutput) {
1511
            return $this->stylelessOutput;
1512
        }
1513
1514
        //if no stylePrefix is set, generate it yourself depending on the script name
1515
        if ('' == $this->stylePrefix) {
1516
            $this->stylePrefix = str_replace('.', '_', $this->_generateFilename()) . '_';
1517
        }
1518
1519
        //set an openInNewWindow_token_to be inserted or not
1520
        if ($this->openInNewWindow) {
1521
            $targetInsert = " target='_blank'";
1522
        }
1523
1524
        // use this array to put the lines in and implode later with "document.write" javascript
1525
        $feedArray = [];
1526
        if (null != $this->image) {
1527
            $imageStr = "<a href='" . $this->image->link . "'" . $targetInsert . '>' . "<img src='" . $this->image->url . "' border='0' alt='" . FeedCreator::iTrunc(htmlspecialchars($this->image->title, ENT_QUOTES | ENT_HTML5), 100) . "' align='" . $this->imageAlign . "' ";
0 ignored issues
show
Bug introduced by
The variable $targetInsert does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
1528
            if ($this->image->width) {
1529
                $imageStr .= " width='" . $this->image->width . "' ";
1530
            }
1531
            if ($this->image->height) {
1532
                $imageStr .= " height='" . $this->image->height . "' ";
1533
            }
1534
            $imageStr    .= '></a>';
1535
            $feedArray[] = $imageStr;
1536
        }
1537
1538
        if ($this->title) {
1539
            $feedArray[] = "<div class='" . $this->stylePrefix . "title'><a href='" . $this->link . "' " . $targetInsert . " class='" . $this->stylePrefix . "title'>" . FeedCreator::iTrunc(htmlspecialchars($this->title, ENT_QUOTES | ENT_HTML5), 100) . '</a></div>';
1540
        }
1541
        if ($this->getDescription()) {
1542
            $feedArray[] = "<div class='" . $this->stylePrefix . "description'>" . str_replace(']]>', '', str_replace('<![CDATA[', '', $this->getDescription())) . '</div>';
1543
        }
1544
1545
        if ($this->header) {
1546
            $feedArray[] = "<div class='" . $this->stylePrefix . "header'>" . $this->header . '</div>';
1547
        }
1548
1549
        for ($i = 0, $iMax = count($this->items); $i < $iMax; ++$i) {
1550
            if ($this->separator && $i > 0) {
1551
                $feedArray[] = "<div class='" . $this->stylePrefix . "separator'>" . $this->separator . '</div>';
1552
            }
1553
1554
            if ($this->items[$i]->title) {
1555
                if ($this->items[$i]->link) {
1556
                    $feedArray[] = "<div class='" . $this->stylePrefix . "item_title'><a href='" . $this->items[$i]->link . "' class='" . $this->stylePrefix . "item_title'" . $targetInsert . '>' . FeedCreator::iTrunc(htmlspecialchars(strip_tags($this->items[$i]->title), ENT_QUOTES | ENT_HTML5), 100) . '</a></div>';
1557
                } else {
1558
                    $feedArray[] = "<div class='" . $this->stylePrefix . "item_title'>" . FeedCreator::iTrunc(htmlspecialchars(strip_tags($this->items[$i]->title), ENT_QUOTES | ENT_HTML5), 100) . '</div>';
1559
                }
1560
            }
1561
            if ($this->items[$i]->getDescription()) {
1562
                $feedArray[] = "<div class='" . $this->stylePrefix . "item_description'>" . str_replace(']]>', '', str_replace('<![CDATA[', '', $this->items[$i]->getDescription())) . '</div>';
1563
            }
1564
        }
1565
        if ($this->footer) {
1566
            $feedArray[] = "<div class='" . $this->stylePrefix . "footer'>" . $this->footer . '</div>';
1567
        }
1568
1569
        $feed = '' . implode($feedArray, "\r\n");
1570
1571
        return $feed;
1572
    }
1573
1574
    /**
1575
     * Overrrides parent to produce .html extensions
1576
     *
1577
     * @return string the feed cache filename
1578
     * @since  1.4
1579
     * @access private
1580
     */
1581
    public function _generateFilename()
1582
    {
1583
        $fileInfo = pathinfo($_SERVER['PHP_SELF']);
1584
1585
        return substr($fileInfo['basename'], 0, -(strlen($fileInfo['extension']) + 1)) . '.html';
1586
    }
1587
}
1588
1589
/**
1590
 * JSCreator is a class that writes a js file to a specific
1591
 * location, overriding the createFeed method of the parent HTMLCreator.
1592
 *
1593
 * @author Pascal Van Hecke
1594
 */
1595
class JSCreator extends HTMLCreator
1596
{
1597
1598
    /**
1599
     * JSCreator constructor.
1600
     */
1601
    public function __construct()
1602
    {
1603
        $this->contentType = 'text/javascript';
1604
    }
1605
1606
    /**
1607
     * writes the javascript
1608
     * @return string the scripts's complete text
1609
     */
1610
    public function createFeed()
1611
    {
1612
        $feed      = parent::createFeed();
1613
        $feedArray = explode("\n", $feed);
1614
1615
        $jsFeed = '';
1616
        foreach ($feedArray as $value) {
1617
            $jsFeed .= "document.write('" . trim(addslashes($value)) . "');\n";
1618
        }
1619
1620
        return $jsFeed;
1621
    }
1622
1623
    /**
1624
     * Overrrides parent to produce .js extensions
1625
     *
1626
     * @return string the feed cache filename
1627
     * @since  1.4
1628
     * @access private
1629
     */
1630
    public function _generateFilename()
1631
    {
1632
        $fileInfo = pathinfo($_SERVER['PHP_SELF']);
1633
1634
        return substr($fileInfo['basename'], 0, -(strlen($fileInfo['extension']) + 1)) . '.js';
1635
    }
1636
}
1637
1638
/*** TEST SCRIPT *********************************************************
1639
 *
1640
 * //include("feedcreator.class.php");
1641
 *
1642
 * $rss = new UniversalFeedCreator();
1643
 * $rss->useCached();
1644
 * $rss->title = "PHP news";
1645
 * $rss->description = "daily news from the PHP scripting world";
1646
 *
1647
 * //optional
1648
 * //$rss->descriptionTruncSize = 500;
1649
 * //$rss->descriptionHtmlSyndicated = true;
1650
 * //$rss->xslStyleSheet = "http://feedster.com/rss20.xsl";
1651
 *
1652
 * $rss->link = "http://www.dailyphp.net/news";
1653
 * $rss->feedURL = "http://www.dailyphp.net/".$PHP_SELF;
1654
 *
1655
 * $image = new FeedImage();
1656
 * $image->title = "dailyphp.net logo";
1657
 * $image->url = "http://www.dailyphp.net/images/logo.gif";
1658
 * $image->link = "http://www.dailyphp.net";
1659
 * $image->description = "Feed provided by dailyphp.net. Click to visit.";
1660
 *
1661
 * //optional
1662
 * $image->descriptionTruncSize = 500;
1663
 * $image->descriptionHtmlSyndicated = true;
1664
 *
1665
 * $rss->image = $image;
1666
 *
1667
 * // get your news items from somewhere, e.g. your database:
1668
 * //mysqli_select_db($dbHost, $dbUser, $dbPass);
1669
 * //$res = mysqli_query("SELECT * FROM news ORDER BY newsdate DESC");
1670
 * //while ($data = mysqli_fetch_object($res)) {
1671
 * $item = new FeedItem();
1672
 * $item->title = "This is an the test title of an item";
1673
 * $item->link = "http://localhost/item/";
1674
 * $item->description = "<b>description in </b><br>HTML";
1675
 *
1676
 * //optional
1677
 * //item->descriptionTruncSize = 500;
1678
 * $item->descriptionHtmlSyndicated = true;
1679
 *
1680
 * $item->date = time();
1681
 * $item->source = "http://www.dailyphp.net";
1682
 * $item->author = "John Doe";
1683
 *
1684
 * $rss->addItem($item);
1685
 * //}
1686
 *
1687
 * // valid format strings are: RSS0.91, RSS1.0, RSS2.0, PIE0.1, MBOX, OPML, ATOM0.3, HTML, JS
1688
 * echo $rss->saveFeed("RSS0.91", "feed.xml");
1689
 ***************************************************************************/
1690