Completed
Push — 3 ( 1d0cff...2b4954 )
by Damian
13:47
created

RSSFeed::outputToBrowser()   A

Complexity

Conditions 3
Paths 4

Size

Total Lines 20
Code Lines 12

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 3
eloc 12
nc 4
nop 0
dl 0
loc 20
rs 9.4285
c 0
b 0
f 0
1
<?php
2
/**
3
 * RSSFeed class
4
 *
5
 * This class is used to create an RSS feed.
6
 * @todo Improve documentation
7
 * @package framework
8
 * @subpackage integration
9
 */
10
class RSSFeed extends ViewableData {
11
12
	/**
13
	 * Casting information for this object's methods.
14
	 * Let's us use $Title.XML in templates
15
	 */
16
	private static $casting = array(
17
		"Title" => "Varchar",
18
		"Description" => "Varchar",
19
		"Link" => "Varchar",
20
	);
21
22
	/**
23
	 * Holds the feed entries
24
	 *
25
	 * @var SS_List
26
	 */
27
	protected $entries;
28
29
	/**
30
	 * Title of the feed
31
	 *
32
	 * @var string
33
	 */
34
	protected $title;
35
36
	/**
37
	 * Description of the feed
38
	 *
39
	 * @var string
40
	 */
41
	protected $description;
42
43
	/**
44
	 * Link to the feed
45
	 *
46
	 * @var string
47
	 */
48
	protected $link;
49
50
	/**
51
	 * Name of the title field of feed entries
52
	 *
53
	 * @var string
54
	 */
55
	protected $titleField;
56
57
	/**
58
	 * Name of the description field of feed entries
59
	 *
60
	 * @var string
61
	 */
62
	protected $descriptionField;
63
64
	/**
65
	 * Name of the author field of feed entries
66
	 *
67
	 * @var string
68
	 */
69
	protected $authorField;
70
71
	/**
72
	 * Last modification of the RSS feed
73
	 *
74
	 * @var int Unix timestamp of the last modification
75
	 */
76
	protected $lastModified;
77
78
	/**
79
	 * ETag for the RSS feed (used for client-site caching)
80
	 *
81
	 * @var string The value for the HTTP ETag header.
82
	 */
83
	protected $etag;
84
85
	/**
86
	 * @var string
87
	 */
88
	protected $template = 'RSSFeed';
89
90
	/**
91
	 * Constructor
92
	 *
93
	 * @param SS_List $entries RSS feed entries
94
	 * @param string $link Link to the feed
95
	 * @param string $title Title of the feed
96
	 * @param string $description Description of the field
97
	 * @param string $titleField Name of the field that should be used for the
98
	 *                           titles for the feed entries
99
	 * @param string $descriptionField Name of the field that should be used
100
	 *                                 for the description for the feed
101
	 *                                 entries
102
	 * @param string $authorField Name of the field that should be used for
103
	 *                            the author for the feed entries
104
	 * @param int $lastModified Unix timestamp of the latest modification
105
	 *                          (latest posting)
106
	 * @param string $etag The ETag is an unique identifier that is changed
107
	 *                         every time the representation does
108
	 */
109
	public function __construct(SS_List $entries, $link, $title,
110
											$description = null, $titleField = "Title",
111
											$descriptionField = "Content", $authorField = null,
112
											$lastModified = null, $etag = null) {
113
		$this->entries = $entries;
114
		$this->link = $link;
115
		$this->description = $description;
116
		$this->title = $title;
117
118
		$this->titleField = $titleField;
119
		$this->descriptionField = $descriptionField;
120
		$this->authorField = $authorField;
121
122
		$this->lastModified = $lastModified;
123
		$this->etag = $etag;
124
125
		parent::__construct();
126
	}
127
128
	/**
129
	 * Include an link to the feed
130
	 *
131
	 * @param string $url URL of the feed
132
	 * @param string $title Title to show
133
	 */
134
	public static function linkToFeed($url, $title = null) {
135
		$title = Convert::raw2xml($title);
136
		Requirements::insertHeadTags(
137
			'<link rel="alternate" type="application/rss+xml" title="' . $title .
138
			'" href="' . $url . '" />');
139
	}
140
141
	/**
142
	 * Get the RSS feed entries
143
	 *
144
	 * @return SS_List Returns the {@link RSSFeed_Entry} objects.
145
	 */
146
	public function Entries() {
147
		$output = new ArrayList();
148
149
		if(isset($this->entries)) {
150
			foreach($this->entries as $entry) {
151
				$output->push(
152
					RSSFeed_Entry::create($entry, $this->titleField, $this->descriptionField, $this->authorField));
153
			}
154
		}
155
		return $output;
156
	}
157
158
	/**
159
	 * Get the title of thisfeed
160
	 *
161
	 * @return string Returns the title of the feed.
162
	 */
163
	public function Title() {
164
		return $this->title;
165
	}
166
167
	/**
168
	 * Get the URL of this feed
169
	 *
170
	 * @param string $action
171
	 * @return string Returns the URL of the feed.
172
	 */
173
	public function Link($action = null) {
174
		return Controller::join_links(Director::absoluteURL($this->link), $action);
175
	}
176
177
	/**
178
	 * Get the description of this feed
179
	 *
180
	 * @return string Returns the description of the feed.
181
	 */
182
	public function Description() {
183
		return $this->description;
184
	}
185
186
	/**
187
	 * Output the feed to the browser.
188
	 *
189
	 * TODO: Pass $response object to ->outputToBrowser() to loosen dependence on global state for easier testing/prototyping so dev can inject custom SS_HTTPResponse instance.
190
	 *
191
	 * @return	HTMLText
192
	 */
193
	public function outputToBrowser() {
194
		$prevState = Config::inst()->get('SSViewer', 'source_file_comments');
195
		Config::inst()->update('SSViewer', 'source_file_comments', false);
196
197
		$response = Controller::curr()->getResponse();
198
199
		if(is_int($this->lastModified)) {
200
			HTTP::register_modification_timestamp($this->lastModified);
201
			$response->addHeader("Last-Modified", gmdate("D, d M Y H:i:s", $this->lastModified) . ' GMT');
202
		}
203
		if(!empty($this->etag)) {
204
			HTTP::register_etag($this->etag);
205
		}
206
207
		$response->addHeader("Content-Type", "application/rss+xml; charset=utf-8");
208
209
		Config::inst()->update('SSViewer', 'source_file_comments', $prevState);
210
211
		return $this->renderWith($this->getTemplate());
212
	}
213
214
	/**
215
	 * Set the name of the template to use. Actual template will be resolved
216
	 * via the standard template inclusion process.
217
	 *
218
	 * @param string
219
	 */
220
	public function setTemplate($template) {
221
		$this->template = $template;
222
	}
223
224
	/**
225
	 * Returns the name of the template to use.
226
	 *
227
	 * @return string
228
	 */
229
	public function getTemplate() {
230
		return $this->template;
231
	}
232
}
233
234
/**
235
 * RSSFeed_Entry class
236
 *
237
 * This class is used for entries of an RSS feed.
238
 *
239
 * @see RSSFeed
240
 * @package framework
241
 * @subpackage integration
242
 */
243
class RSSFeed_Entry extends ViewableData {
244
	/**
245
	 * The object that represents the item, it contains all the data.
246
	 *
247
	 * @var mixed
248
	 */
249
	protected $failover;
250
251
	/**
252
	 * Name of the title field of feed entries
253
	 *
254
	 * @var string
255
	 */
256
	protected $titleField;
257
258
	/**
259
	 * Name of the description field of feed entries
260
	 *
261
	 * @var string
262
	 */
263
	protected $descriptionField;
264
265
	/**
266
	 * Name of the author field of feed entries
267
	 *
268
	 * @var string
269
	 */
270
	protected $authorField;
271
272
	/**
273
	 * Create a new RSSFeed entry.
274
	 */
275
	public function __construct($entry, $titleField, $descriptionField,
276
											$authorField) {
277
		$this->failover = $entry;
278
		$this->titleField = $titleField;
279
		$this->descriptionField = $descriptionField;
280
		$this->authorField = $authorField;
281
282
		parent::__construct();
283
	}
284
285
	/**
286
	 * Get the description of this entry
287
	 *
288
	 * @return string Returns the description of the entry.
289
	 */
290
	public function Title() {
291
		return $this->rssField($this->titleField, 'Varchar');
292
	}
293
294
	/**
295
	 * Get the description of this entry
296
	 *
297
	 * @return string Returns the description of the entry.
298
	 */
299
	public function Description() {
300
		return $this->rssField($this->descriptionField, 'HTMLText');
301
	}
302
303
	/**
304
	 * Get the author of this entry
305
	 *
306
	 * @return string Returns the author of the entry.
307
	 */
308
	public function Author() {
309
		if($this->authorField) return $this->failover->obj($this->authorField);
310
	}
311
312
	/**
313
	 * Return the named field as an obj() call from $this->failover.
314
	 * Default to the given class if there's no casting information.
315
	 */
316
	public function rssField($fieldName, $defaultClass = 'Varchar') {
317
		if($fieldName) {
318
			if($this->failover->castingHelper($fieldName)) {
319
				$value = $this->failover->$fieldName;
320
				$obj = $this->failover->obj($fieldName);
321
				$obj->setValue($value);
322
				return $obj;
323
			} else {
324
				$obj = new $defaultClass($fieldName);
325
				$obj->setValue($this->failover->XML_val($fieldName));
326
				return $obj;
327
			}
328
		}
329
	}
330
331
	/**
332
	 * Get a link to this entry
333
	 *
334
	 * @return string Returns the URL of this entry
335
	 */
336
	public function AbsoluteLink() {
337
		if($this->failover->hasMethod('AbsoluteLink')) {
338
			return $this->failover->AbsoluteLink();
339
		} else if($this->failover->hasMethod('Link')) {
340
			return Director::absoluteURL($this->failover->Link());
341
		} else {
342
			user_error($this->failover->class . " object has neither an AbsoluteLink nor a Link method."
343
				. " Can't put a link in the RSS feed", E_USER_WARNING);
344
		}
345
	}
346
}
347