|
1 <?php |
|
2 |
|
3 /** |
|
4 * Zend Framework |
|
5 * |
|
6 * LICENSE |
|
7 * |
|
8 * This source file is subject to the new BSD license that is bundled |
|
9 * with this package in the file LICENSE.txt. |
|
10 * It is also available through the world-wide-web at this URL: |
|
11 * http://framework.zend.com/license/new-bsd |
|
12 * If you did not receive a copy of the license and are unable to |
|
13 * obtain it through the world-wide-web, please send an email |
|
14 * to license@zend.com so we can send you a copy immediately. |
|
15 * |
|
16 * @category Zend |
|
17 * @package Zend_Feed |
|
18 * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) |
|
19 * @license http://framework.zend.com/license/new-bsd New BSD License |
|
20 * @version $Id: Builder.php 20096 2010-01-06 02:05:09Z bkarwin $ |
|
21 */ |
|
22 |
|
23 |
|
24 /** |
|
25 * @see Zend_Feed_Builder_Interface |
|
26 */ |
|
27 require_once 'Zend/Feed/Builder/Interface.php'; |
|
28 |
|
29 /** |
|
30 * @see Zend_Feed_Builder_Header |
|
31 */ |
|
32 require_once 'Zend/Feed/Builder/Header.php'; |
|
33 |
|
34 /** |
|
35 * @see Zend_Feed_Builder_Entry |
|
36 */ |
|
37 require_once 'Zend/Feed/Builder/Entry.php'; |
|
38 |
|
39 |
|
40 /** |
|
41 * A simple implementation of Zend_Feed_Builder_Interface. |
|
42 * |
|
43 * Users are encouraged to make their own classes to implement Zend_Feed_Builder_Interface |
|
44 * |
|
45 * @category Zend |
|
46 * @package Zend_Feed |
|
47 * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) |
|
48 * @license http://framework.zend.com/license/new-bsd New BSD License |
|
49 */ |
|
50 class Zend_Feed_Builder implements Zend_Feed_Builder_Interface |
|
51 { |
|
52 /** |
|
53 * The data of the feed |
|
54 * |
|
55 * @var $_data array |
|
56 */ |
|
57 private $_data; |
|
58 |
|
59 /** |
|
60 * Header of the feed |
|
61 * |
|
62 * @var $_header Zend_Feed_Builder_Header |
|
63 */ |
|
64 private $_header; |
|
65 |
|
66 /** |
|
67 * List of the entries of the feed |
|
68 * |
|
69 * @var $_entries array |
|
70 */ |
|
71 private $_entries = array(); |
|
72 |
|
73 /** |
|
74 * Constructor. The $data array must conform to the following format: |
|
75 * <code> |
|
76 * array( |
|
77 * 'title' => 'title of the feed', //required |
|
78 * 'link' => 'canonical url to the feed', //required |
|
79 * 'lastUpdate' => 'timestamp of the update date', // optional |
|
80 * 'published' => 'timestamp of the publication date', //optional |
|
81 * 'charset' => 'charset', // required |
|
82 * 'description' => 'short description of the feed', //optional |
|
83 * 'author' => 'author/publisher of the feed', //optional |
|
84 * 'email' => 'email of the author', //optional |
|
85 * 'webmaster' => 'email address for person responsible for technical issues' // optional, ignored if atom is used |
|
86 * 'copyright' => 'copyright notice', //optional |
|
87 * 'image' => 'url to image', //optional |
|
88 * 'generator' => 'generator', // optional |
|
89 * 'language' => 'language the feed is written in', // optional |
|
90 * 'ttl' => 'how long in minutes a feed can be cached before refreshing', // optional, ignored if atom is used |
|
91 * 'rating' => 'The PICS rating for the channel.', // optional, ignored if atom is used |
|
92 * 'cloud' => array( |
|
93 * 'domain' => 'domain of the cloud, e.g. rpc.sys.com' // required |
|
94 * 'port' => 'port to connect to' // optional, default to 80 |
|
95 * 'path' => 'path of the cloud, e.g. /RPC2 //required |
|
96 * 'registerProcedure' => 'procedure to call, e.g. myCloud.rssPleaseNotify' // required |
|
97 * 'protocol' => 'protocol to use, e.g. soap or xml-rpc' // required |
|
98 * ), a cloud to be notified of updates // optional, ignored if atom is used |
|
99 * 'textInput' => array( |
|
100 * 'title' => 'the label of the Submit button in the text input area' // required, |
|
101 * 'description' => 'explains the text input area' // required |
|
102 * 'name' => 'the name of the text object in the text input area' // required |
|
103 * 'link' => 'the URL of the CGI script that processes text input requests' // required |
|
104 * ) // a text input box that can be displayed with the feed // optional, ignored if atom is used |
|
105 * 'skipHours' => array( |
|
106 * 'hour in 24 format', // e.g 13 (1pm) |
|
107 * // up to 24 rows whose value is a number between 0 and 23 |
|
108 * ) // Hint telling aggregators which hours they can skip // optional, ignored if atom is used |
|
109 * 'skipDays ' => array( |
|
110 * 'a day to skip', // e.g Monday |
|
111 * // up to 7 rows whose value is a Monday, Tuesday, Wednesday, Thursday, Friday, Saturday or Sunday |
|
112 * ) // Hint telling aggregators which days they can skip // optional, ignored if atom is used |
|
113 * 'itunes' => array( |
|
114 * 'author' => 'Artist column' // optional, default to the main author value |
|
115 * 'owner' => array( |
|
116 * 'name' => 'name of the owner' // optional, default to main author value |
|
117 * 'email' => 'email of the owner' // optional, default to main email value |
|
118 * ) // Owner of the podcast // optional |
|
119 * 'image' => 'album/podcast art' // optional, default to the main image value |
|
120 * 'subtitle' => 'short description' // optional, default to the main description value |
|
121 * 'summary' => 'longer description' // optional, default to the main description value |
|
122 * 'block' => 'Prevent an episode from appearing (yes|no)' // optional |
|
123 * 'category' => array( |
|
124 * array('main' => 'main category', // required |
|
125 * 'sub' => 'sub category' // optional |
|
126 * ), |
|
127 * // up to 3 rows |
|
128 * ) // 'Category column and in iTunes Music Store Browse' // required |
|
129 * 'explicit' => 'parental advisory graphic (yes|no|clean)' // optional |
|
130 * 'keywords' => 'a comma separated list of 12 keywords maximum' // optional |
|
131 * 'new-feed-url' => 'used to inform iTunes of new feed URL location' // optional |
|
132 * ) // Itunes extension data // optional, ignored if atom is used |
|
133 * 'entries' => array( |
|
134 * array( |
|
135 * 'title' => 'title of the feed entry', //required |
|
136 * 'link' => 'url to a feed entry', //required |
|
137 * 'description' => 'short version of a feed entry', // only text, no html, required |
|
138 * 'guid' => 'id of the article, if not given link value will used', //optional |
|
139 * 'content' => 'long version', // can contain html, optional |
|
140 * 'lastUpdate' => 'timestamp of the publication date', // optional |
|
141 * 'comments' => 'comments page of the feed entry', // optional |
|
142 * 'commentRss' => 'the feed url of the associated comments', // optional |
|
143 * 'source' => array( |
|
144 * 'title' => 'title of the original source' // required, |
|
145 * 'url' => 'url of the original source' // required |
|
146 * ) // original source of the feed entry // optional |
|
147 * 'category' => array( |
|
148 * array( |
|
149 * 'term' => 'first category label' // required, |
|
150 * 'scheme' => 'url that identifies a categorization scheme' // optional |
|
151 * ), |
|
152 * array( |
|
153 * //data for the second category and so on |
|
154 * ) |
|
155 * ) // list of the attached categories // optional |
|
156 * 'enclosure' => array( |
|
157 * array( |
|
158 * 'url' => 'url of the linked enclosure' // required |
|
159 * 'type' => 'mime type of the enclosure' // optional |
|
160 * 'length' => 'length of the linked content in octets' // optional |
|
161 * ), |
|
162 * array( |
|
163 * //data for the second enclosure and so on |
|
164 * ) |
|
165 * ) // list of the enclosures of the feed entry // optional |
|
166 * ), |
|
167 * array( |
|
168 * //data for the second entry and so on |
|
169 * ) |
|
170 * ) |
|
171 * ); |
|
172 * </code> |
|
173 * |
|
174 * @param array $data |
|
175 * @return void |
|
176 */ |
|
177 public function __construct(array $data) |
|
178 { |
|
179 $this->_data = $data; |
|
180 $this->_createHeader($data); |
|
181 if (isset($data['entries'])) { |
|
182 $this->_createEntries($data['entries']); |
|
183 } |
|
184 } |
|
185 |
|
186 /** |
|
187 * Returns an instance of Zend_Feed_Builder_Header |
|
188 * describing the header of the feed |
|
189 * |
|
190 * @return Zend_Feed_Builder_Header |
|
191 */ |
|
192 public function getHeader() |
|
193 { |
|
194 return $this->_header; |
|
195 } |
|
196 |
|
197 /** |
|
198 * Returns an array of Zend_Feed_Builder_Entry instances |
|
199 * describing the entries of the feed |
|
200 * |
|
201 * @return array of Zend_Feed_Builder_Entry |
|
202 */ |
|
203 public function getEntries() |
|
204 { |
|
205 return $this->_entries; |
|
206 } |
|
207 |
|
208 /** |
|
209 * Create the Zend_Feed_Builder_Header instance |
|
210 * |
|
211 * @param array $data |
|
212 * @throws Zend_Feed_Builder_Exception |
|
213 * @return void |
|
214 */ |
|
215 protected function _createHeader(array $data) |
|
216 { |
|
217 $mandatories = array('title', 'link', 'charset'); |
|
218 foreach ($mandatories as $mandatory) { |
|
219 if (!isset($data[$mandatory])) { |
|
220 /** |
|
221 * @see Zend_Feed_Builder_Exception |
|
222 */ |
|
223 require_once 'Zend/Feed/Builder/Exception.php'; |
|
224 throw new Zend_Feed_Builder_Exception("$mandatory key is missing"); |
|
225 } |
|
226 } |
|
227 $this->_header = new Zend_Feed_Builder_Header($data['title'], $data['link'], $data['charset']); |
|
228 if (isset($data['lastUpdate'])) { |
|
229 $this->_header->setLastUpdate($data['lastUpdate']); |
|
230 } |
|
231 if (isset($data['published'])) { |
|
232 $this->_header->setPublishedDate($data['published']); |
|
233 } |
|
234 if (isset($data['description'])) { |
|
235 $this->_header->setDescription($data['description']); |
|
236 } |
|
237 if (isset($data['author'])) { |
|
238 $this->_header->setAuthor($data['author']); |
|
239 } |
|
240 if (isset($data['email'])) { |
|
241 $this->_header->setEmail($data['email']); |
|
242 } |
|
243 if (isset($data['webmaster'])) { |
|
244 $this->_header->setWebmaster($data['webmaster']); |
|
245 } |
|
246 if (isset($data['copyright'])) { |
|
247 $this->_header->setCopyright($data['copyright']); |
|
248 } |
|
249 if (isset($data['image'])) { |
|
250 $this->_header->setImage($data['image']); |
|
251 } |
|
252 if (isset($data['generator'])) { |
|
253 $this->_header->setGenerator($data['generator']); |
|
254 } |
|
255 if (isset($data['language'])) { |
|
256 $this->_header->setLanguage($data['language']); |
|
257 } |
|
258 if (isset($data['ttl'])) { |
|
259 $this->_header->setTtl($data['ttl']); |
|
260 } |
|
261 if (isset($data['rating'])) { |
|
262 $this->_header->setRating($data['rating']); |
|
263 } |
|
264 if (isset($data['cloud'])) { |
|
265 $mandatories = array('domain', 'path', 'registerProcedure', 'protocol'); |
|
266 foreach ($mandatories as $mandatory) { |
|
267 if (!isset($data['cloud'][$mandatory])) { |
|
268 /** |
|
269 * @see Zend_Feed_Builder_Exception |
|
270 */ |
|
271 require_once 'Zend/Feed/Builder/Exception.php'; |
|
272 throw new Zend_Feed_Builder_Exception("you have to define $mandatory property of your cloud"); |
|
273 } |
|
274 } |
|
275 $uri_str = 'http://' . $data['cloud']['domain'] . $data['cloud']['path']; |
|
276 $this->_header->setCloud($uri_str, $data['cloud']['registerProcedure'], $data['cloud']['protocol']); |
|
277 } |
|
278 if (isset($data['textInput'])) { |
|
279 $mandatories = array('title', 'description', 'name', 'link'); |
|
280 foreach ($mandatories as $mandatory) { |
|
281 if (!isset($data['textInput'][$mandatory])) { |
|
282 /** |
|
283 * @see Zend_Feed_Builder_Exception |
|
284 */ |
|
285 require_once 'Zend/Feed/Builder/Exception.php'; |
|
286 throw new Zend_Feed_Builder_Exception("you have to define $mandatory property of your textInput"); |
|
287 } |
|
288 } |
|
289 $this->_header->setTextInput($data['textInput']['title'], |
|
290 $data['textInput']['description'], |
|
291 $data['textInput']['name'], |
|
292 $data['textInput']['link']); |
|
293 } |
|
294 if (isset($data['skipHours'])) { |
|
295 $this->_header->setSkipHours($data['skipHours']); |
|
296 } |
|
297 if (isset($data['skipDays'])) { |
|
298 $this->_header->setSkipDays($data['skipDays']); |
|
299 } |
|
300 if (isset($data['itunes'])) { |
|
301 $itunes = new Zend_Feed_Builder_Header_Itunes($data['itunes']['category']); |
|
302 if (isset($data['itunes']['author'])) { |
|
303 $itunes->setAuthor($data['itunes']['author']); |
|
304 } |
|
305 if (isset($data['itunes']['owner'])) { |
|
306 $name = isset($data['itunes']['owner']['name']) ? $data['itunes']['owner']['name'] : ''; |
|
307 $email = isset($data['itunes']['owner']['email']) ? $data['itunes']['owner']['email'] : ''; |
|
308 $itunes->setOwner($name, $email); |
|
309 } |
|
310 if (isset($data['itunes']['image'])) { |
|
311 $itunes->setImage($data['itunes']['image']); |
|
312 } |
|
313 if (isset($data['itunes']['subtitle'])) { |
|
314 $itunes->setSubtitle($data['itunes']['subtitle']); |
|
315 } |
|
316 if (isset($data['itunes']['summary'])) { |
|
317 $itunes->setSummary($data['itunes']['summary']); |
|
318 } |
|
319 if (isset($data['itunes']['block'])) { |
|
320 $itunes->setBlock($data['itunes']['block']); |
|
321 } |
|
322 if (isset($data['itunes']['explicit'])) { |
|
323 $itunes->setExplicit($data['itunes']['explicit']); |
|
324 } |
|
325 if (isset($data['itunes']['keywords'])) { |
|
326 $itunes->setKeywords($data['itunes']['keywords']); |
|
327 } |
|
328 if (isset($data['itunes']['new-feed-url'])) { |
|
329 $itunes->setNewFeedUrl($data['itunes']['new-feed-url']); |
|
330 } |
|
331 |
|
332 $this->_header->setITunes($itunes); |
|
333 } |
|
334 } |
|
335 |
|
336 /** |
|
337 * Create the array of article entries |
|
338 * |
|
339 * @param array $data |
|
340 * @throws Zend_Feed_Builder_Exception |
|
341 * @return void |
|
342 */ |
|
343 protected function _createEntries(array $data) |
|
344 { |
|
345 foreach ($data as $row) { |
|
346 $mandatories = array('title', 'link', 'description'); |
|
347 foreach ($mandatories as $mandatory) { |
|
348 if (!isset($row[$mandatory])) { |
|
349 /** |
|
350 * @see Zend_Feed_Builder_Exception |
|
351 */ |
|
352 require_once 'Zend/Feed/Builder/Exception.php'; |
|
353 throw new Zend_Feed_Builder_Exception("$mandatory key is missing"); |
|
354 } |
|
355 } |
|
356 $entry = new Zend_Feed_Builder_Entry($row['title'], $row['link'], $row['description']); |
|
357 if (isset($row['author'])) { |
|
358 $entry->setAuthor($row['author']); |
|
359 } |
|
360 if (isset($row['guid'])) { |
|
361 $entry->setId($row['guid']); |
|
362 } |
|
363 if (isset($row['content'])) { |
|
364 $entry->setContent($row['content']); |
|
365 } |
|
366 if (isset($row['lastUpdate'])) { |
|
367 $entry->setLastUpdate($row['lastUpdate']); |
|
368 } |
|
369 if (isset($row['comments'])) { |
|
370 $entry->setCommentsUrl($row['comments']); |
|
371 } |
|
372 if (isset($row['commentRss'])) { |
|
373 $entry->setCommentsRssUrl($row['commentRss']); |
|
374 } |
|
375 if (isset($row['source'])) { |
|
376 $mandatories = array('title', 'url'); |
|
377 foreach ($mandatories as $mandatory) { |
|
378 if (!isset($row['source'][$mandatory])) { |
|
379 /** |
|
380 * @see Zend_Feed_Builder_Exception |
|
381 */ |
|
382 require_once 'Zend/Feed/Builder/Exception.php'; |
|
383 throw new Zend_Feed_Builder_Exception("$mandatory key of source property is missing"); |
|
384 } |
|
385 } |
|
386 $entry->setSource($row['source']['title'], $row['source']['url']); |
|
387 } |
|
388 if (isset($row['category'])) { |
|
389 $entry->setCategories($row['category']); |
|
390 } |
|
391 if (isset($row['enclosure'])) { |
|
392 $entry->setEnclosures($row['enclosure']); |
|
393 } |
|
394 |
|
395 $this->_entries[] = $entry; |
|
396 } |
|
397 } |
|
398 } |