Chris@0
|
1 <?php
|
Chris@0
|
2 /**
|
Chris@0
|
3 * Zend Framework (http://framework.zend.com/)
|
Chris@0
|
4 *
|
Chris@0
|
5 * @link http://github.com/zendframework/zf2 for the canonical source repository
|
Chris@0
|
6 * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
|
Chris@0
|
7 * @license http://framework.zend.com/license/new-bsd New BSD License
|
Chris@0
|
8 */
|
Chris@0
|
9
|
Chris@0
|
10 namespace Zend\Feed\Writer\Extension\ITunes;
|
Chris@0
|
11
|
Chris@0
|
12 use Zend\Feed\Uri;
|
Chris@0
|
13 use Zend\Feed\Writer;
|
Chris@0
|
14 use Zend\Stdlib\StringUtils;
|
Chris@0
|
15 use Zend\Stdlib\StringWrapper\StringWrapperInterface;
|
Chris@0
|
16
|
Chris@0
|
17 class Feed
|
Chris@0
|
18 {
|
Chris@0
|
19 /**
|
Chris@0
|
20 * Array of Feed data for rendering by Extension's renderers
|
Chris@0
|
21 *
|
Chris@0
|
22 * @var array
|
Chris@0
|
23 */
|
Chris@0
|
24 protected $data = [];
|
Chris@0
|
25
|
Chris@0
|
26 /**
|
Chris@0
|
27 * Encoding of all text values
|
Chris@0
|
28 *
|
Chris@0
|
29 * @var string
|
Chris@0
|
30 */
|
Chris@0
|
31 protected $encoding = 'UTF-8';
|
Chris@0
|
32
|
Chris@0
|
33 /**
|
Chris@0
|
34 * The used string wrapper supporting encoding
|
Chris@0
|
35 *
|
Chris@0
|
36 * @var StringWrapperInterface
|
Chris@0
|
37 */
|
Chris@0
|
38 protected $stringWrapper;
|
Chris@0
|
39
|
Chris@0
|
40 /**
|
Chris@0
|
41 * Constructor
|
Chris@0
|
42 */
|
Chris@0
|
43 public function __construct()
|
Chris@0
|
44 {
|
Chris@0
|
45 $this->stringWrapper = StringUtils::getWrapper($this->encoding);
|
Chris@0
|
46 }
|
Chris@0
|
47
|
Chris@0
|
48 /**
|
Chris@0
|
49 * Set feed encoding
|
Chris@0
|
50 *
|
Chris@0
|
51 * @param string $enc
|
Chris@0
|
52 * @return Feed
|
Chris@0
|
53 */
|
Chris@0
|
54 public function setEncoding($enc)
|
Chris@0
|
55 {
|
Chris@0
|
56 $this->stringWrapper = StringUtils::getWrapper($enc);
|
Chris@0
|
57 $this->encoding = $enc;
|
Chris@0
|
58 return $this;
|
Chris@0
|
59 }
|
Chris@0
|
60
|
Chris@0
|
61 /**
|
Chris@0
|
62 * Get feed encoding
|
Chris@0
|
63 *
|
Chris@0
|
64 * @return string
|
Chris@0
|
65 */
|
Chris@0
|
66 public function getEncoding()
|
Chris@0
|
67 {
|
Chris@0
|
68 return $this->encoding;
|
Chris@0
|
69 }
|
Chris@0
|
70
|
Chris@0
|
71 /**
|
Chris@0
|
72 * Set a block value of "yes" or "no". You may also set an empty string.
|
Chris@0
|
73 *
|
Chris@0
|
74 * @param string
|
Chris@0
|
75 * @return Feed
|
Chris@0
|
76 * @throws Writer\Exception\InvalidArgumentException
|
Chris@0
|
77 */
|
Chris@0
|
78 public function setItunesBlock($value)
|
Chris@0
|
79 {
|
Chris@12
|
80 if (! ctype_alpha($value) && strlen($value) > 0) {
|
Chris@0
|
81 throw new Writer\Exception\InvalidArgumentException('invalid parameter: "block" may only'
|
Chris@0
|
82 . ' contain alphabetic characters');
|
Chris@0
|
83 }
|
Chris@0
|
84 if ($this->stringWrapper->strlen($value) > 255) {
|
Chris@0
|
85 throw new Writer\Exception\InvalidArgumentException('invalid parameter: "block" may only'
|
Chris@0
|
86 . ' contain a maximum of 255 characters');
|
Chris@0
|
87 }
|
Chris@0
|
88 $this->data['block'] = $value;
|
Chris@0
|
89 return $this;
|
Chris@0
|
90 }
|
Chris@0
|
91
|
Chris@0
|
92 /**
|
Chris@0
|
93 * Add feed authors
|
Chris@0
|
94 *
|
Chris@0
|
95 * @param array $values
|
Chris@0
|
96 * @return Feed
|
Chris@0
|
97 */
|
Chris@0
|
98 public function addItunesAuthors(array $values)
|
Chris@0
|
99 {
|
Chris@0
|
100 foreach ($values as $value) {
|
Chris@0
|
101 $this->addItunesAuthor($value);
|
Chris@0
|
102 }
|
Chris@0
|
103 return $this;
|
Chris@0
|
104 }
|
Chris@0
|
105
|
Chris@0
|
106 /**
|
Chris@0
|
107 * Add feed author
|
Chris@0
|
108 *
|
Chris@0
|
109 * @param string $value
|
Chris@0
|
110 * @return Feed
|
Chris@0
|
111 * @throws Writer\Exception\InvalidArgumentException
|
Chris@0
|
112 */
|
Chris@0
|
113 public function addItunesAuthor($value)
|
Chris@0
|
114 {
|
Chris@0
|
115 if ($this->stringWrapper->strlen($value) > 255) {
|
Chris@0
|
116 throw new Writer\Exception\InvalidArgumentException('invalid parameter: any "author" may only'
|
Chris@0
|
117 . ' contain a maximum of 255 characters each');
|
Chris@0
|
118 }
|
Chris@12
|
119 if (! isset($this->data['authors'])) {
|
Chris@0
|
120 $this->data['authors'] = [];
|
Chris@0
|
121 }
|
Chris@0
|
122 $this->data['authors'][] = $value;
|
Chris@0
|
123 return $this;
|
Chris@0
|
124 }
|
Chris@0
|
125
|
Chris@0
|
126 /**
|
Chris@0
|
127 * Set feed categories
|
Chris@0
|
128 *
|
Chris@0
|
129 * @param array $values
|
Chris@0
|
130 * @return Feed
|
Chris@0
|
131 * @throws Writer\Exception\InvalidArgumentException
|
Chris@0
|
132 */
|
Chris@0
|
133 public function setItunesCategories(array $values)
|
Chris@0
|
134 {
|
Chris@12
|
135 if (! isset($this->data['categories'])) {
|
Chris@0
|
136 $this->data['categories'] = [];
|
Chris@0
|
137 }
|
Chris@0
|
138 foreach ($values as $key => $value) {
|
Chris@12
|
139 if (! is_array($value)) {
|
Chris@0
|
140 if ($this->stringWrapper->strlen($value) > 255) {
|
Chris@0
|
141 throw new Writer\Exception\InvalidArgumentException('invalid parameter: any "category" may only'
|
Chris@0
|
142 . ' contain a maximum of 255 characters each');
|
Chris@0
|
143 }
|
Chris@0
|
144 $this->data['categories'][] = $value;
|
Chris@0
|
145 } else {
|
Chris@0
|
146 if ($this->stringWrapper->strlen($key) > 255) {
|
Chris@0
|
147 throw new Writer\Exception\InvalidArgumentException('invalid parameter: any "category" may only'
|
Chris@0
|
148 . ' contain a maximum of 255 characters each');
|
Chris@0
|
149 }
|
Chris@0
|
150 $this->data['categories'][$key] = [];
|
Chris@0
|
151 foreach ($value as $val) {
|
Chris@0
|
152 if ($this->stringWrapper->strlen($val) > 255) {
|
Chris@0
|
153 throw new Writer\Exception\InvalidArgumentException('invalid parameter: any "category" may only'
|
Chris@0
|
154 . ' contain a maximum of 255 characters each');
|
Chris@0
|
155 }
|
Chris@0
|
156 $this->data['categories'][$key][] = $val;
|
Chris@0
|
157 }
|
Chris@0
|
158 }
|
Chris@0
|
159 }
|
Chris@0
|
160 return $this;
|
Chris@0
|
161 }
|
Chris@0
|
162
|
Chris@0
|
163 /**
|
Chris@0
|
164 * Set feed image (icon)
|
Chris@0
|
165 *
|
Chris@0
|
166 * @param string $value
|
Chris@0
|
167 * @return Feed
|
Chris@0
|
168 * @throws Writer\Exception\InvalidArgumentException
|
Chris@0
|
169 */
|
Chris@0
|
170 public function setItunesImage($value)
|
Chris@0
|
171 {
|
Chris@16
|
172 if (! is_string($value) || ! Uri::factory($value)->isValid()) {
|
Chris@0
|
173 throw new Writer\Exception\InvalidArgumentException('invalid parameter: "image" may only'
|
Chris@0
|
174 . ' be a valid URI/IRI');
|
Chris@0
|
175 }
|
Chris@12
|
176 if (! in_array(substr($value, -3), ['jpg', 'png'])) {
|
Chris@0
|
177 throw new Writer\Exception\InvalidArgumentException('invalid parameter: "image" may only'
|
Chris@0
|
178 . ' use file extension "jpg" or "png" which must be the last three'
|
Chris@0
|
179 . ' characters of the URI (i.e. no query string or fragment)');
|
Chris@0
|
180 }
|
Chris@0
|
181 $this->data['image'] = $value;
|
Chris@0
|
182 return $this;
|
Chris@0
|
183 }
|
Chris@0
|
184
|
Chris@0
|
185 /**
|
Chris@0
|
186 * Set feed cumulative duration
|
Chris@0
|
187 *
|
Chris@0
|
188 * @param string $value
|
Chris@0
|
189 * @return Feed
|
Chris@0
|
190 * @throws Writer\Exception\InvalidArgumentException
|
Chris@0
|
191 */
|
Chris@0
|
192 public function setItunesDuration($value)
|
Chris@0
|
193 {
|
Chris@0
|
194 $value = (string) $value;
|
Chris@12
|
195 if (! ctype_digit($value)
|
Chris@12
|
196 && ! preg_match("/^\d+:[0-5]{1}[0-9]{1}$/", $value)
|
Chris@12
|
197 && ! preg_match("/^\d+:[0-5]{1}[0-9]{1}:[0-5]{1}[0-9]{1}$/", $value)
|
Chris@0
|
198 ) {
|
Chris@0
|
199 throw new Writer\Exception\InvalidArgumentException('invalid parameter: "duration" may only'
|
Chris@0
|
200 . ' be of a specified [[HH:]MM:]SS format');
|
Chris@0
|
201 }
|
Chris@0
|
202 $this->data['duration'] = $value;
|
Chris@0
|
203 return $this;
|
Chris@0
|
204 }
|
Chris@0
|
205
|
Chris@0
|
206 /**
|
Chris@0
|
207 * Set "explicit" flag
|
Chris@0
|
208 *
|
Chris@0
|
209 * @param bool $value
|
Chris@0
|
210 * @return Feed
|
Chris@0
|
211 * @throws Writer\Exception\InvalidArgumentException
|
Chris@0
|
212 */
|
Chris@0
|
213 public function setItunesExplicit($value)
|
Chris@0
|
214 {
|
Chris@12
|
215 if (! in_array($value, ['yes', 'no', 'clean'])) {
|
Chris@0
|
216 throw new Writer\Exception\InvalidArgumentException('invalid parameter: "explicit" may only'
|
Chris@0
|
217 . ' be one of "yes", "no" or "clean"');
|
Chris@0
|
218 }
|
Chris@0
|
219 $this->data['explicit'] = $value;
|
Chris@0
|
220 return $this;
|
Chris@0
|
221 }
|
Chris@0
|
222
|
Chris@0
|
223 /**
|
Chris@0
|
224 * Set feed keywords
|
Chris@0
|
225 *
|
Chris@16
|
226 * @deprecated since 2.10.0; itunes:keywords is no longer part of the
|
Chris@16
|
227 * iTunes podcast RSS specification.
|
Chris@0
|
228 * @param array $value
|
Chris@0
|
229 * @return Feed
|
Chris@0
|
230 * @throws Writer\Exception\InvalidArgumentException
|
Chris@0
|
231 */
|
Chris@0
|
232 public function setItunesKeywords(array $value)
|
Chris@0
|
233 {
|
Chris@16
|
234 trigger_error(
|
Chris@16
|
235 'itunes:keywords has been deprecated in the iTunes podcast RSS specification,'
|
Chris@16
|
236 . ' and should not be relied on.',
|
Chris@16
|
237 \E_USER_DEPRECATED
|
Chris@16
|
238 );
|
Chris@16
|
239
|
Chris@0
|
240 if (count($value) > 12) {
|
Chris@0
|
241 throw new Writer\Exception\InvalidArgumentException('invalid parameter: "keywords" may only'
|
Chris@0
|
242 . ' contain a maximum of 12 terms');
|
Chris@0
|
243 }
|
Chris@0
|
244 $concat = implode(',', $value);
|
Chris@0
|
245 if ($this->stringWrapper->strlen($concat) > 255) {
|
Chris@0
|
246 throw new Writer\Exception\InvalidArgumentException('invalid parameter: "keywords" may only'
|
Chris@0
|
247 . ' have a concatenated length of 255 chars where terms are delimited'
|
Chris@0
|
248 . ' by a comma');
|
Chris@0
|
249 }
|
Chris@0
|
250 $this->data['keywords'] = $value;
|
Chris@0
|
251 return $this;
|
Chris@0
|
252 }
|
Chris@0
|
253
|
Chris@0
|
254 /**
|
Chris@0
|
255 * Set new feed URL
|
Chris@0
|
256 *
|
Chris@0
|
257 * @param string $value
|
Chris@0
|
258 * @return Feed
|
Chris@0
|
259 * @throws Writer\Exception\InvalidArgumentException
|
Chris@0
|
260 */
|
Chris@0
|
261 public function setItunesNewFeedUrl($value)
|
Chris@0
|
262 {
|
Chris@12
|
263 if (! Uri::factory($value)->isValid()) {
|
Chris@0
|
264 throw new Writer\Exception\InvalidArgumentException('invalid parameter: "newFeedUrl" may only'
|
Chris@0
|
265 . ' be a valid URI/IRI');
|
Chris@0
|
266 }
|
Chris@0
|
267 $this->data['newFeedUrl'] = $value;
|
Chris@0
|
268 return $this;
|
Chris@0
|
269 }
|
Chris@0
|
270
|
Chris@0
|
271 /**
|
Chris@0
|
272 * Add feed owners
|
Chris@0
|
273 *
|
Chris@0
|
274 * @param array $values
|
Chris@0
|
275 * @return Feed
|
Chris@0
|
276 */
|
Chris@0
|
277 public function addItunesOwners(array $values)
|
Chris@0
|
278 {
|
Chris@0
|
279 foreach ($values as $value) {
|
Chris@0
|
280 $this->addItunesOwner($value);
|
Chris@0
|
281 }
|
Chris@0
|
282 return $this;
|
Chris@0
|
283 }
|
Chris@0
|
284
|
Chris@0
|
285 /**
|
Chris@0
|
286 * Add feed owner
|
Chris@0
|
287 *
|
Chris@0
|
288 * @param array $value
|
Chris@0
|
289 * @return Feed
|
Chris@0
|
290 * @throws Writer\Exception\InvalidArgumentException
|
Chris@0
|
291 */
|
Chris@0
|
292 public function addItunesOwner(array $value)
|
Chris@0
|
293 {
|
Chris@12
|
294 if (! isset($value['name']) || ! isset($value['email'])) {
|
Chris@0
|
295 throw new Writer\Exception\InvalidArgumentException('invalid parameter: any "owner" must'
|
Chris@0
|
296 . ' be an array containing keys "name" and "email"');
|
Chris@0
|
297 }
|
Chris@0
|
298 if ($this->stringWrapper->strlen($value['name']) > 255
|
Chris@0
|
299 || $this->stringWrapper->strlen($value['email']) > 255
|
Chris@0
|
300 ) {
|
Chris@0
|
301 throw new Writer\Exception\InvalidArgumentException('invalid parameter: any "owner" may only'
|
Chris@0
|
302 . ' contain a maximum of 255 characters each for "name" and "email"');
|
Chris@0
|
303 }
|
Chris@12
|
304 if (! isset($this->data['owners'])) {
|
Chris@0
|
305 $this->data['owners'] = [];
|
Chris@0
|
306 }
|
Chris@0
|
307 $this->data['owners'][] = $value;
|
Chris@0
|
308 return $this;
|
Chris@0
|
309 }
|
Chris@0
|
310
|
Chris@0
|
311 /**
|
Chris@0
|
312 * Set feed subtitle
|
Chris@0
|
313 *
|
Chris@0
|
314 * @param string $value
|
Chris@0
|
315 * @return Feed
|
Chris@0
|
316 * @throws Writer\Exception\InvalidArgumentException
|
Chris@0
|
317 */
|
Chris@0
|
318 public function setItunesSubtitle($value)
|
Chris@0
|
319 {
|
Chris@0
|
320 if ($this->stringWrapper->strlen($value) > 255) {
|
Chris@0
|
321 throw new Writer\Exception\InvalidArgumentException('invalid parameter: "subtitle" may only'
|
Chris@0
|
322 . ' contain a maximum of 255 characters');
|
Chris@0
|
323 }
|
Chris@0
|
324 $this->data['subtitle'] = $value;
|
Chris@0
|
325 return $this;
|
Chris@0
|
326 }
|
Chris@0
|
327
|
Chris@0
|
328 /**
|
Chris@0
|
329 * Set feed summary
|
Chris@0
|
330 *
|
Chris@0
|
331 * @param string $value
|
Chris@0
|
332 * @return Feed
|
Chris@0
|
333 * @throws Writer\Exception\InvalidArgumentException
|
Chris@0
|
334 */
|
Chris@0
|
335 public function setItunesSummary($value)
|
Chris@0
|
336 {
|
Chris@0
|
337 if ($this->stringWrapper->strlen($value) > 4000) {
|
Chris@0
|
338 throw new Writer\Exception\InvalidArgumentException('invalid parameter: "summary" may only'
|
Chris@0
|
339 . ' contain a maximum of 4000 characters');
|
Chris@0
|
340 }
|
Chris@0
|
341 $this->data['summary'] = $value;
|
Chris@0
|
342 return $this;
|
Chris@0
|
343 }
|
Chris@0
|
344
|
Chris@0
|
345 /**
|
Chris@16
|
346 * Set podcast type
|
Chris@16
|
347 *
|
Chris@16
|
348 * @param string $type
|
Chris@16
|
349 * @return Feed
|
Chris@16
|
350 * @throws Writer\Exception\InvalidArgumentException
|
Chris@16
|
351 */
|
Chris@16
|
352 public function setItunesType($type)
|
Chris@16
|
353 {
|
Chris@16
|
354 $validTypes = ['episodic', 'serial'];
|
Chris@16
|
355 if (! in_array($type, $validTypes, true)) {
|
Chris@16
|
356 throw new Writer\Exception\InvalidArgumentException(sprintf(
|
Chris@16
|
357 'invalid parameter: "type" MUST be one of [%s]; received %s',
|
Chris@16
|
358 implode(', ', $validTypes),
|
Chris@16
|
359 is_object($type) ? get_class($type) : var_export($type, true)
|
Chris@16
|
360 ));
|
Chris@16
|
361 }
|
Chris@16
|
362 $this->data['type'] = $type;
|
Chris@16
|
363 return $this;
|
Chris@16
|
364 }
|
Chris@16
|
365
|
Chris@16
|
366 /**
|
Chris@16
|
367 * Set "completion" status (whether more episodes will be released)
|
Chris@16
|
368 *
|
Chris@16
|
369 * @param bool $status
|
Chris@16
|
370 * @return Feed
|
Chris@16
|
371 * @throws Writer\Exception\InvalidArgumentException
|
Chris@16
|
372 */
|
Chris@16
|
373 public function setItunesComplete($status)
|
Chris@16
|
374 {
|
Chris@16
|
375 if (! is_bool($status)) {
|
Chris@16
|
376 throw new Writer\Exception\InvalidArgumentException(sprintf(
|
Chris@16
|
377 'invalid parameter: "complete" MUST be boolean; received %s',
|
Chris@16
|
378 is_object($status) ? get_class($status) : var_export($status, true)
|
Chris@16
|
379 ));
|
Chris@16
|
380 }
|
Chris@16
|
381
|
Chris@16
|
382 if (! $status) {
|
Chris@16
|
383 return $this;
|
Chris@16
|
384 }
|
Chris@16
|
385
|
Chris@16
|
386 $this->data['complete'] = 'Yes';
|
Chris@16
|
387 return $this;
|
Chris@16
|
388 }
|
Chris@16
|
389
|
Chris@16
|
390 /**
|
Chris@0
|
391 * Overloading: proxy to internal setters
|
Chris@0
|
392 *
|
Chris@0
|
393 * @param string $method
|
Chris@0
|
394 * @param array $params
|
Chris@0
|
395 * @return mixed
|
Chris@0
|
396 * @throws Writer\Exception\BadMethodCallException
|
Chris@0
|
397 */
|
Chris@0
|
398 public function __call($method, array $params)
|
Chris@0
|
399 {
|
Chris@0
|
400 $point = lcfirst(substr($method, 9));
|
Chris@12
|
401 if (! method_exists($this, 'setItunes' . ucfirst($point))
|
Chris@12
|
402 && ! method_exists($this, 'addItunes' . ucfirst($point))
|
Chris@0
|
403 ) {
|
Chris@0
|
404 throw new Writer\Exception\BadMethodCallException(
|
Chris@0
|
405 'invalid method: ' . $method
|
Chris@0
|
406 );
|
Chris@0
|
407 }
|
Chris@16
|
408
|
Chris@12
|
409 if (! array_key_exists($point, $this->data) || empty($this->data[$point])) {
|
Chris@0
|
410 return;
|
Chris@0
|
411 }
|
Chris@0
|
412 return $this->data[$point];
|
Chris@0
|
413 }
|
Chris@0
|
414 }
|