Completed
Push — 4 ( 5fbfd8...bd8494 )
by Ingo
09:20
created

RSSFeed::outputToBrowser()   A

Complexity

Conditions 3
Paths 4

Size

Total Lines 19
Code Lines 11

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 3
eloc 11
nc 4
nop 0
dl 0
loc 19
rs 9.4285
c 0
b 0
f 0
1
<?php
2
3
namespace SilverStripe\Control\RSS;
4
5
use SilverStripe\Control\Middleware\HTTPCacheControlMiddleware;
6
use SilverStripe\ORM\SS_List;
7
use SilverStripe\ORM\ArrayList;
8
use SilverStripe\ORM\FieldType\DBHTMLText;
9
use SilverStripe\Core\Convert;
10
use SilverStripe\Control\Director;
11
use SilverStripe\Control\Controller;
12
use SilverStripe\Control\HTTP;
13
use SilverStripe\View\Requirements;
14
use SilverStripe\View\SSViewer;
15
use SilverStripe\View\ViewableData;
16
17
/**
18
 * RSSFeed class
19
 *
20
 * This class is used to create an RSS feed.
21
 * @todo Improve documentation
22
 */
23
class RSSFeed extends ViewableData
24
{
25
26
    /**
27
     * Casting information for this object's methods.
28
     * Let's us use $Title.XML in templates
29
     */
30
    private static $casting = array(
0 ignored issues
show
introduced by
The private property $casting is not used, and could be removed.
Loading history...
31
        "Title" => "Varchar",
32
        "Description" => "Varchar",
33
        "Link" => "Varchar",
34
    );
35
36
    /**
37
     * Holds the feed entries
38
     *
39
     * @var SS_List
40
     */
41
    protected $entries;
42
43
    /**
44
     * Title of the feed
45
     *
46
     * @var string
47
     */
48
    protected $title;
49
50
    /**
51
     * Description of the feed
52
     *
53
     * @var string
54
     */
55
    protected $description;
56
57
    /**
58
     * Link to the feed
59
     *
60
     * @var string
61
     */
62
    protected $link;
63
64
    /**
65
     * Name of the title field of feed entries
66
     *
67
     * @var string
68
     */
69
    protected $titleField;
70
71
    /**
72
     * Name of the description field of feed entries
73
     *
74
     * @var string
75
     */
76
    protected $descriptionField;
77
78
    /**
79
     * Name of the author field of feed entries
80
     *
81
     * @var string
82
     */
83
    protected $authorField;
84
85
    /**
86
     * Last modification of the RSS feed
87
     *
88
     * @var int Unix timestamp of the last modification
89
     */
90
    protected $lastModified;
91
92
    /**
93
     * ETag for the RSS feed (used for client-site caching)
94
     *
95
     * @var string The value for the HTTP ETag header.
96
     */
97
    protected $etag;
98
99
    /**
100
     * Custom template
101
     *
102
     * @var string
103
     */
104
    protected $template = null;
105
106
    /**
107
     * Constructor
108
     *
109
     * @param SS_List $entries RSS feed entries
110
     * @param string $link Link to the feed
111
     * @param string $title Title of the feed
112
     * @param string $description Description of the field
113
     * @param string $titleField Name of the field that should be used for the
114
     *                           titles for the feed entries
115
     * @param string $descriptionField Name of the field that should be used
116
     *                                 for the description for the feed
117
     *                                 entries
118
     * @param string $authorField Name of the field that should be used for
119
     *                            the author for the feed entries
120
     * @param int $lastModified Unix timestamp of the latest modification
121
     *                          (latest posting)
122
     * @param string $etag The ETag is an unique identifier that is changed
123
     *                         every time the representation does
124
     */
125
    public function __construct(
126
        SS_List $entries,
127
        $link,
128
        $title,
129
        $description = null,
130
        $titleField = "Title",
131
        $descriptionField = "Content",
132
        $authorField = null,
133
        $lastModified = null,
134
        $etag = null
135
    ) {
136
        $this->entries = $entries;
137
        $this->link = $link;
138
        $this->description = $description;
139
        $this->title = $title;
140
141
        $this->titleField = $titleField;
142
        $this->descriptionField = $descriptionField;
143
        $this->authorField = $authorField;
144
145
        $this->lastModified = $lastModified;
146
        $this->etag = $etag;
147
148
        parent::__construct();
149
    }
150
151
    /**
152
     * Include an link to the feed
153
     *
154
     * @param string $url URL of the feed
155
     * @param string $title Title to show
156
     */
157
    public static function linkToFeed($url, $title = null)
158
    {
159
        $title = Convert::raw2xml($title);
160
        Requirements::insertHeadTags(
161
            '<link rel="alternate" type="application/rss+xml" title="' . $title . '" href="' . $url . '" />'
162
        );
163
    }
164
165
    /**
166
     * Get the RSS feed entries
167
     *
168
     * @return SS_List Returns the {@link RSSFeed_Entry} objects.
169
     */
170
    public function Entries()
171
    {
172
        $output = new ArrayList();
173
174
        if (isset($this->entries)) {
175
            foreach ($this->entries as $entry) {
176
                $output->push(
177
                    RSSFeed_Entry::create($entry, $this->titleField, $this->descriptionField, $this->authorField)
178
                );
179
            }
180
        }
181
        return $output;
182
    }
183
184
    /**
185
     * Get the title of thisfeed
186
     *
187
     * @return string Returns the title of the feed.
188
     */
189
    public function Title()
190
    {
191
        return $this->title;
192
    }
193
194
    /**
195
     * Get the URL of this feed
196
     *
197
     * @param string $action
198
     * @return string Returns the URL of the feed.
199
     */
200
    public function Link($action = null)
201
    {
202
        return Controller::join_links(Director::absoluteURL($this->link), $action);
203
    }
204
205
    /**
206
     * Get the description of this feed
207
     *
208
     * @return string Returns the description of the feed.
209
     */
210
    public function Description()
211
    {
212
        return $this->description;
213
    }
214
215
    /**
216
     * Output the feed to the browser.
217
     *
218
     * TODO: Pass $response object to ->outputToBrowser() to loosen dependence on global state for easier testing/prototyping so dev can inject custom HTTPResponse instance.
219
     *
220
     * @return DBHTMLText
221
     */
222
    public function outputToBrowser()
223
    {
224
        $prevState = SSViewer::config()->uninherited('source_file_comments');
225
        SSViewer::config()->update('source_file_comments', false);
226
227
        $response = Controller::curr()->getResponse();
228
229
        if (is_int($this->lastModified)) {
0 ignored issues
show
introduced by
The condition is_int($this->lastModified) is always true.
Loading history...
230
            HTTPCacheControlMiddleware::singleton()->registerModificationDate($this->lastModified);
231
            $response->addHeader("Last-Modified", gmdate("D, d M Y H:i:s", $this->lastModified) . ' GMT');
232
        }
233
        if (!empty($this->etag)) {
234
            $response->addHeader('ETag', "\"{$this->etag}\"");
235
        }
236
237
        $response->addHeader("Content-Type", "application/rss+xml; charset=utf-8");
238
239
        SSViewer::config()->update('source_file_comments', $prevState);
240
        return $this->renderWith($this->getTemplates());
241
    }
242
243
    /**
244
     * Set the name of the template to use. Actual template will be resolved
245
     * via the standard template inclusion process.
246
     *
247
     * @param string
248
     */
249
    public function setTemplate($template)
250
    {
251
        $this->template = $template;
252
    }
253
254
    /**
255
     * Returns the name of the template to use.
256
     *
257
     * @return string
258
     */
259
    public function getTemplate()
260
    {
261
        return $this->template;
262
    }
263
264
    /**
265
     * Returns the ordered list of preferred templates for rendering this object.
266
     * Will prioritise any custom template first, and then templates based on class hiearchy next.
267
     *
268
     * @return array
269
     */
270
    public function getTemplates()
271
    {
272
        $templates = SSViewer::get_templates_by_class(static::class, '', __CLASS__);
273
        // Prefer any custom template
274
        if ($this->getTemplate()) {
275
            array_unshift($templates, $this->getTemplate());
276
        }
277
        return $templates;
278
    }
279
}
280