File indexing completed on 2024-05-12 06:02:31

0001 <?php
0002 
0003 /**
0004  * Zend Framework
0005  *
0006  * LICENSE
0007  *
0008  * This source file is subject to the new BSD license that is bundled
0009  * with this package in the file LICENSE.txt.
0010  * It is also available through the world-wide-web at this URL:
0011  * http://framework.zend.com/license/new-bsd
0012  * If you did not receive a copy of the license and are unable to
0013  * obtain it through the world-wide-web, please send an email
0014  * to license@zend.com so we can send you a copy immediately.
0015  *
0016  * @category   Zend
0017  * @package    Zend_Feed
0018  * @copyright  Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
0019  * @license    http://framework.zend.com/license/new-bsd     New BSD License
0020  * @version    $Id$
0021  */
0022 
0023 
0024 /**
0025  * @see Zend_Feed_Builder_Interface
0026  */
0027 // require_once 'Zend/Feed/Builder/Interface.php';
0028 
0029 /**
0030  * @see Zend_Feed_Builder_Header
0031  */
0032 // require_once 'Zend/Feed/Builder/Header.php';
0033 
0034 /**
0035  * @see Zend_Feed_Builder_Entry
0036  */
0037 // require_once 'Zend/Feed/Builder/Entry.php';
0038 
0039 
0040 /**
0041  * A simple implementation of Zend_Feed_Builder_Interface.
0042  *
0043  * Users are encouraged to make their own classes to implement Zend_Feed_Builder_Interface
0044  *
0045  * @category   Zend
0046  * @package    Zend_Feed
0047  * @copyright  Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
0048  * @license    http://framework.zend.com/license/new-bsd     New BSD License
0049  */
0050 class Zend_Feed_Builder implements Zend_Feed_Builder_Interface
0051 {
0052     /**
0053      * The data of the feed
0054      *
0055      * @var $_data array
0056      */
0057     private $_data;
0058 
0059     /**
0060      * Header of the feed
0061      *
0062      * @var $_header Zend_Feed_Builder_Header
0063      */
0064     private $_header;
0065 
0066     /**
0067      * List of the entries of the feed
0068      *
0069      * @var $_entries array
0070      */
0071     private $_entries = array();
0072 
0073     /**
0074      * Constructor. The $data array must conform to the following format:
0075      * <code>
0076      *  array(
0077      *  'title'       => 'title of the feed', //required
0078      *  'link'        => 'canonical url to the feed', //required
0079      *  'lastUpdate'  => 'timestamp of the update date', // optional
0080      *  'published'   => 'timestamp of the publication date', //optional
0081      *  'charset'     => 'charset', // required
0082      *  'description' => 'short description of the feed', //optional
0083      *  'author'      => 'author/publisher of the feed', //optional
0084      *  'email'       => 'email of the author', //optional
0085      *  'webmaster'   => 'email address for person responsible for technical issues' // optional, ignored if atom is used
0086      *  'copyright'   => 'copyright notice', //optional
0087      *  'image'       => 'url to image', //optional
0088      *  'generator'   => 'generator', // optional
0089      *  'language'    => 'language the feed is written in', // optional
0090      *  'ttl'         => 'how long in minutes a feed can be cached before refreshing', // optional, ignored if atom is used
0091      *  'rating'      => 'The PICS rating for the channel.', // optional, ignored if atom is used
0092      *  'cloud'       => array(
0093      *                    'domain'            => 'domain of the cloud, e.g. rpc.sys.com' // required
0094      *                    'port'              => 'port to connect to' // optional, default to 80
0095      *                    'path'              => 'path of the cloud, e.g. /RPC2 //required
0096      *                    'registerProcedure' => 'procedure to call, e.g. myCloud.rssPleaseNotify' // required
0097      *                    'protocol'          => 'protocol to use, e.g. soap or xml-rpc' // required
0098      *                    ), a cloud to be notified of updates // optional, ignored if atom is used
0099      *  'textInput'   => array(
0100      *                    'title'       => 'the label of the Submit button in the text input area' // required,
0101      *                    'description' => 'explains the text input area' // required
0102      *                    'name'        => 'the name of the text object in the text input area' // required
0103      *                    'link'        => 'the URL of the CGI script that processes text input requests' // required
0104      *                    ) // a text input box that can be displayed with the feed // optional, ignored if atom is used
0105      *  'skipHours'   => array(
0106      *                    'hour in 24 format', // e.g 13 (1pm)
0107      *                    // up to 24 rows whose value is a number between 0 and 23
0108      *                    ) // Hint telling aggregators which hours they can skip // optional, ignored if atom is used
0109      *  'skipDays '   => array(
0110      *                    'a day to skip', // e.g Monday
0111      *                    // up to 7 rows whose value is a Monday, Tuesday, Wednesday, Thursday, Friday, Saturday or Sunday
0112      *                    ) // Hint telling aggregators which days they can skip // optional, ignored if atom is used
0113      *  'itunes'      => array(
0114      *                    'author'       => 'Artist column' // optional, default to the main author value
0115      *                    'owner'        => array(
0116      *                                        'name' => 'name of the owner' // optional, default to main author value
0117      *                                        'email' => 'email of the owner' // optional, default to main email value
0118      *                                        ) // Owner of the podcast // optional
0119      *                    'image'        => 'album/podcast art' // optional, default to the main image value
0120      *                    'subtitle'     => 'short description' // optional, default to the main description value
0121      *                    'summary'      => 'longer description' // optional, default to the main description value
0122      *                    'block'        => 'Prevent an episode from appearing (yes|no)' // optional
0123      *                    'category'     => array(
0124      *                                      array('main' => 'main category', // required
0125      *                                            'sub'  => 'sub category' // optional
0126      *                                        ),
0127      *                                        // up to 3 rows
0128      *                                        ) // 'Category column and in iTunes Music Store Browse' // required
0129      *                    'explicit'     => 'parental advisory graphic (yes|no|clean)' // optional
0130      *                    'keywords'     => 'a comma separated list of 12 keywords maximum' // optional
0131      *                    'new-feed-url' => 'used to inform iTunes of new feed URL location' // optional
0132      *                    ) // Itunes extension data // optional, ignored if atom is used
0133      *  'entries'     => array(
0134      *                   array(
0135      *                    'title'        => 'title of the feed entry', //required
0136      *                    'link'         => 'url to a feed entry', //required
0137      *                    'description'  => 'short version of a feed entry', // only text, no html, required
0138      *                    'guid'         => 'id of the article, if not given link value will used', //optional
0139      *                    'content'      => 'long version', // can contain html, optional
0140      *                    'lastUpdate'   => 'timestamp of the publication date', // optional
0141      *                    'comments'     => 'comments page of the feed entry', // optional
0142      *                    'commentRss'   => 'the feed url of the associated comments', // optional
0143      *                    'source'       => array(
0144      *                                        'title' => 'title of the original source' // required,
0145      *                                        'url' => 'url of the original source' // required
0146      *                                           ) // original source of the feed entry // optional
0147      *                    'category'     => array(
0148      *                                      array(
0149      *                                        'term' => 'first category label' // required,
0150      *                                        'scheme' => 'url that identifies a categorization scheme' // optional
0151      *                                            ),
0152      *                                      array(
0153      *                                         //data for the second category and so on
0154      *                                           )
0155      *                                        ) // list of the attached categories // optional
0156      *                    'enclosure'    => array(
0157      *                                      array(
0158      *                                        'url' => 'url of the linked enclosure' // required
0159      *                                        'type' => 'mime type of the enclosure' // optional
0160      *                                        'length' => 'length of the linked content in octets' // optional
0161      *                                           ),
0162      *                                      array(
0163      *                                         //data for the second enclosure and so on
0164      *                                           )
0165      *                                        ) // list of the enclosures of the feed entry // optional
0166      *                   ),
0167      *                   array(
0168      *                   //data for the second entry and so on
0169      *                   )
0170      *                 )
0171      * );
0172      * </code>
0173      *
0174      * @param  array $data
0175      * @return void
0176      */
0177     public function __construct(array $data)
0178     {
0179         $this->_data = $data;
0180         $this->_createHeader($data);
0181         if (isset($data['entries'])) {
0182             $this->_createEntries($data['entries']);
0183         }
0184     }
0185 
0186     /**
0187      * Returns an instance of Zend_Feed_Builder_Header
0188      * describing the header of the feed
0189      *
0190      * @return Zend_Feed_Builder_Header
0191      */
0192     public function getHeader()
0193     {
0194         return $this->_header;
0195     }
0196 
0197     /**
0198      * Returns an array of Zend_Feed_Builder_Entry instances
0199      * describing the entries of the feed
0200      *
0201      * @return array of Zend_Feed_Builder_Entry
0202      */
0203     public function getEntries()
0204     {
0205         return $this->_entries;
0206     }
0207 
0208     /**
0209      * Create the Zend_Feed_Builder_Header instance
0210      *
0211      * @param  array $data
0212      * @throws Zend_Feed_Builder_Exception
0213      * @return void
0214      */
0215     protected function _createHeader(array $data)
0216     {
0217         $mandatories = array('title', 'link', 'charset');
0218         foreach ($mandatories as $mandatory) {
0219             if (!isset($data[$mandatory])) {
0220                 /**
0221                  * @see Zend_Feed_Builder_Exception
0222                  */
0223                 // require_once 'Zend/Feed/Builder/Exception.php';
0224                 throw new Zend_Feed_Builder_Exception("$mandatory key is missing");
0225             }
0226         }
0227         $this->_header = new Zend_Feed_Builder_Header($data['title'], $data['link'], $data['charset']);
0228         if (isset($data['lastUpdate'])) {
0229             $this->_header->setLastUpdate($data['lastUpdate']);
0230         }
0231         if (isset($data['published'])) {
0232             $this->_header->setPublishedDate($data['published']);
0233         }
0234         if (isset($data['description'])) {
0235             $this->_header->setDescription($data['description']);
0236         }
0237         if (isset($data['author'])) {
0238             $this->_header->setAuthor($data['author']);
0239         }
0240         if (isset($data['email'])) {
0241             $this->_header->setEmail($data['email']);
0242         }
0243         if (isset($data['webmaster'])) {
0244             $this->_header->setWebmaster($data['webmaster']);
0245         }
0246         if (isset($data['copyright'])) {
0247             $this->_header->setCopyright($data['copyright']);
0248         }
0249         if (isset($data['image'])) {
0250             $this->_header->setImage($data['image']);
0251         }
0252         if (isset($data['generator'])) {
0253             $this->_header->setGenerator($data['generator']);
0254         }
0255         if (isset($data['language'])) {
0256             $this->_header->setLanguage($data['language']);
0257         }
0258         if (isset($data['ttl'])) {
0259             $this->_header->setTtl($data['ttl']);
0260         }
0261         if (isset($data['rating'])) {
0262             $this->_header->setRating($data['rating']);
0263         }
0264         if (isset($data['cloud'])) {
0265             $mandatories = array('domain', 'path', 'registerProcedure', 'protocol');
0266             foreach ($mandatories as $mandatory) {
0267                 if (!isset($data['cloud'][$mandatory])) {
0268                     /**
0269                      * @see Zend_Feed_Builder_Exception
0270                      */
0271                     // require_once 'Zend/Feed/Builder/Exception.php';
0272                     throw new Zend_Feed_Builder_Exception("you have to define $mandatory property of your cloud");
0273                 }
0274             }
0275             $uri_str = 'http://' . $data['cloud']['domain'] . $data['cloud']['path'];
0276             $this->_header->setCloud($uri_str, $data['cloud']['registerProcedure'], $data['cloud']['protocol']);
0277         }
0278         if (isset($data['textInput'])) {
0279             $mandatories = array('title', 'description', 'name', 'link');
0280             foreach ($mandatories as $mandatory) {
0281                 if (!isset($data['textInput'][$mandatory])) {
0282                     /**
0283                      * @see Zend_Feed_Builder_Exception
0284                      */
0285                     // require_once 'Zend/Feed/Builder/Exception.php';
0286                     throw new Zend_Feed_Builder_Exception("you have to define $mandatory property of your textInput");
0287                 }
0288             }
0289             $this->_header->setTextInput($data['textInput']['title'],
0290                                          $data['textInput']['description'],
0291                                          $data['textInput']['name'],
0292                                          $data['textInput']['link']);
0293         }
0294         if (isset($data['skipHours'])) {
0295             $this->_header->setSkipHours($data['skipHours']);
0296         }
0297         if (isset($data['skipDays'])) {
0298             $this->_header->setSkipDays($data['skipDays']);
0299         }
0300         if (isset($data['itunes'])) {
0301             $itunes = new Zend_Feed_Builder_Header_Itunes($data['itunes']['category']);
0302             if (isset($data['itunes']['author'])) {
0303                 $itunes->setAuthor($data['itunes']['author']);
0304             }
0305             if (isset($data['itunes']['owner'])) {
0306                 $name = isset($data['itunes']['owner']['name']) ? $data['itunes']['owner']['name'] : '';
0307                 $email = isset($data['itunes']['owner']['email']) ? $data['itunes']['owner']['email'] : '';
0308                 $itunes->setOwner($name, $email);
0309             }
0310             if (isset($data['itunes']['image'])) {
0311                 $itunes->setImage($data['itunes']['image']);
0312             }
0313             if (isset($data['itunes']['subtitle'])) {
0314                 $itunes->setSubtitle($data['itunes']['subtitle']);
0315             }
0316             if (isset($data['itunes']['summary'])) {
0317                 $itunes->setSummary($data['itunes']['summary']);
0318             }
0319             if (isset($data['itunes']['block'])) {
0320                 $itunes->setBlock($data['itunes']['block']);
0321             }
0322             if (isset($data['itunes']['explicit'])) {
0323                 $itunes->setExplicit($data['itunes']['explicit']);
0324             }
0325             if (isset($data['itunes']['keywords'])) {
0326                 $itunes->setKeywords($data['itunes']['keywords']);
0327             }
0328             if (isset($data['itunes']['new-feed-url'])) {
0329                 $itunes->setNewFeedUrl($data['itunes']['new-feed-url']);
0330             }
0331 
0332             $this->_header->setITunes($itunes);
0333         }
0334     }
0335 
0336     /**
0337      * Create the array of article entries
0338      *
0339      * @param  array $data
0340      * @throws Zend_Feed_Builder_Exception
0341      * @return void
0342      */
0343     protected function _createEntries(array $data)
0344     {
0345         foreach ($data as $row) {
0346             $mandatories = array('title', 'link', 'description');
0347             foreach ($mandatories as $mandatory) {
0348                 if (!isset($row[$mandatory])) {
0349                     /**
0350                      * @see Zend_Feed_Builder_Exception
0351                      */
0352                     // require_once 'Zend/Feed/Builder/Exception.php';
0353                     throw new Zend_Feed_Builder_Exception("$mandatory key is missing");
0354                 }
0355             }
0356             $entry = new Zend_Feed_Builder_Entry($row['title'], $row['link'], $row['description']);
0357             if (isset($row['author'])) {
0358                 $entry->setAuthor($row['author']);
0359             }
0360             if (isset($row['guid'])) {
0361                 $entry->setId($row['guid']);
0362             }
0363             if (isset($row['content'])) {
0364                 $entry->setContent($row['content']);
0365             }
0366             if (isset($row['lastUpdate'])) {
0367                 $entry->setLastUpdate($row['lastUpdate']);
0368             }
0369             if (isset($row['comments'])) {
0370                 $entry->setCommentsUrl($row['comments']);
0371             }
0372             if (isset($row['commentRss'])) {
0373                 $entry->setCommentsRssUrl($row['commentRss']);
0374             }
0375             if (isset($row['source'])) {
0376                 $mandatories = array('title', 'url');
0377                 foreach ($mandatories as $mandatory) {
0378                     if (!isset($row['source'][$mandatory])) {
0379                         /**
0380                          * @see Zend_Feed_Builder_Exception
0381                          */
0382                         // require_once 'Zend/Feed/Builder/Exception.php';
0383                         throw new Zend_Feed_Builder_Exception("$mandatory key of source property is missing");
0384                     }
0385                 }
0386                 $entry->setSource($row['source']['title'], $row['source']['url']);
0387             }
0388             if (isset($row['category'])) {
0389                 $entry->setCategories($row['category']);
0390             }
0391             if (isset($row['enclosure'])) {
0392                 $entry->setEnclosures($row['enclosure']);
0393             }
0394 
0395             $this->_entries[] = $entry;
0396         }
0397     }
0398 }