web/Zend/Feed/Atom.php
changeset 0 4eba9c11703f
equal deleted inserted replaced
-1:000000000000 0:4eba9c11703f
       
     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: Atom.php 20096 2010-01-06 02:05:09Z bkarwin $
       
    21  */
       
    22 
       
    23 
       
    24 /**
       
    25  * @see Zend_Feed_Abstract
       
    26  */
       
    27 require_once 'Zend/Feed/Abstract.php';
       
    28 
       
    29 /**
       
    30  * @see Zend_Feed_Entry_Atom
       
    31  */
       
    32 require_once 'Zend/Feed/Entry/Atom.php';
       
    33 
       
    34 
       
    35 /**
       
    36  * Atom feed class
       
    37  *
       
    38  * The Zend_Feed_Atom class is a concrete subclass of the general
       
    39  * Zend_Feed_Abstract class, tailored for representing an Atom
       
    40  * feed. It shares all of the same methods with its abstract
       
    41  * parent. The distinction is made in the format of data that
       
    42  * Zend_Feed_Atom expects, and as a further pointer for users as to
       
    43  * what kind of feed object they have been passed.
       
    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_Atom extends Zend_Feed_Abstract
       
    51 {
       
    52 
       
    53     /**
       
    54      * The classname for individual feed elements.
       
    55      *
       
    56      * @var string
       
    57      */
       
    58     protected $_entryClassName = 'Zend_Feed_Entry_Atom';
       
    59 
       
    60     /**
       
    61      * The element name for individual feed elements (Atom <entry>
       
    62      * elements).
       
    63      *
       
    64      * @var string
       
    65      */
       
    66     protected $_entryElementName = 'entry';
       
    67 
       
    68     /**
       
    69      * The default namespace for Atom feeds.
       
    70      *
       
    71      * @var string
       
    72      */
       
    73     protected $_defaultNamespace = 'atom';
       
    74 
       
    75 
       
    76     /**
       
    77      * Override Zend_Feed_Abstract to set up the $_element and $_entries aliases.
       
    78      *
       
    79      * @return void
       
    80      * @throws Zend_Feed_Exception
       
    81      */
       
    82     public function __wakeup()
       
    83     {
       
    84         parent::__wakeup();
       
    85 
       
    86         // Find the base feed element and create an alias to it.
       
    87         $element = $this->_element->getElementsByTagName('feed')->item(0);
       
    88         if (!$element) {
       
    89             // Try to find a single <entry> instead.
       
    90             $element = $this->_element->getElementsByTagName($this->_entryElementName)->item(0);
       
    91             if (!$element) {
       
    92                 /**
       
    93                  * @see Zend_Feed_Exception
       
    94                  */
       
    95                 require_once 'Zend/Feed/Exception.php';
       
    96                 throw new Zend_Feed_Exception('No root <feed> or <' . $this->_entryElementName
       
    97                                               . '> element found, cannot parse feed.');
       
    98             }
       
    99 
       
   100             $doc = new DOMDocument($this->_element->version,
       
   101                                    $this->_element->actualEncoding);
       
   102             $feed = $doc->appendChild($doc->createElement('feed'));
       
   103             $feed->appendChild($doc->importNode($element, true));
       
   104             $element = $feed;
       
   105         }
       
   106 
       
   107         $this->_element = $element;
       
   108 
       
   109         // Find the entries and save a pointer to them for speed and
       
   110         // simplicity.
       
   111         $this->_buildEntryCache();
       
   112     }
       
   113 
       
   114 
       
   115     /**
       
   116      * Easy access to <link> tags keyed by "rel" attributes.
       
   117      *
       
   118      * If $elt->link() is called with no arguments, we will attempt to
       
   119      * return the value of the <link> tag(s) like all other
       
   120      * method-syntax attribute access. If an argument is passed to
       
   121      * link(), however, then we will return the "href" value of the
       
   122      * first <link> tag that has a "rel" attribute matching $rel:
       
   123      *
       
   124      * $elt->link(): returns the value of the link tag.
       
   125      * $elt->link('self'): returns the href from the first <link rel="self"> in the entry.
       
   126      *
       
   127      * @param  string $rel The "rel" attribute to look for.
       
   128      * @return mixed
       
   129      */
       
   130     public function link($rel = null)
       
   131     {
       
   132         if ($rel === null) {
       
   133             return parent::__call('link', null);
       
   134         }
       
   135 
       
   136         // index link tags by their "rel" attribute.
       
   137         $links = parent::__get('link');
       
   138         if (!is_array($links)) {
       
   139             if ($links instanceof Zend_Feed_Element) {
       
   140                 $links = array($links);
       
   141             } else {
       
   142                 return $links;
       
   143             }
       
   144         }
       
   145 
       
   146         foreach ($links as $link) {
       
   147             if (empty($link['rel'])) {
       
   148                 continue;
       
   149             }
       
   150             if ($rel == $link['rel']) {
       
   151                 return $link['href'];
       
   152             }
       
   153         }
       
   154 
       
   155         return null;
       
   156     }
       
   157 
       
   158 
       
   159     /**
       
   160      * Make accessing some individual elements of the feed easier.
       
   161      *
       
   162      * Special accessors 'entry' and 'entries' are provided so that if
       
   163      * you wish to iterate over an Atom feed's entries, you can do so
       
   164      * using foreach ($feed->entries as $entry) or foreach
       
   165      * ($feed->entry as $entry).
       
   166      *
       
   167      * @param  string $var The property to access.
       
   168      * @return mixed
       
   169      */
       
   170     public function __get($var)
       
   171     {
       
   172         switch ($var) {
       
   173             case 'entry':
       
   174                 // fall through to the next case
       
   175             case 'entries':
       
   176                 return $this;
       
   177 
       
   178             default:
       
   179                 return parent::__get($var);
       
   180         }
       
   181     }
       
   182 
       
   183     /**
       
   184      * Generate the header of the feed when working in write mode
       
   185      *
       
   186      * @param  array $array the data to use
       
   187      * @return DOMElement root node
       
   188      */
       
   189     protected function _mapFeedHeaders($array)
       
   190     {
       
   191         $feed = $this->_element->createElement('feed');
       
   192         $feed->setAttribute('xmlns', 'http://www.w3.org/2005/Atom');
       
   193 
       
   194         $id = $this->_element->createElement('id', $array->link);
       
   195         $feed->appendChild($id);
       
   196 
       
   197         $title = $this->_element->createElement('title');
       
   198         $title->appendChild($this->_element->createCDATASection($array->title));
       
   199         $feed->appendChild($title);
       
   200 
       
   201         if (isset($array->author)) {
       
   202             $author = $this->_element->createElement('author');
       
   203             $name = $this->_element->createElement('name', $array->author);
       
   204             $author->appendChild($name);
       
   205             if (isset($array->email)) {
       
   206                 $email = $this->_element->createElement('email', $array->email);
       
   207                 $author->appendChild($email);
       
   208             }
       
   209             $feed->appendChild($author);
       
   210         }
       
   211 
       
   212         $updated = isset($array->lastUpdate) ? $array->lastUpdate : time();
       
   213         $updated = $this->_element->createElement('updated', date(DATE_ATOM, $updated));
       
   214         $feed->appendChild($updated);
       
   215 
       
   216         if (isset($array->published)) {
       
   217             $published = $this->_element->createElement('published', date(DATE_ATOM, $array->published));
       
   218             $feed->appendChild($published);
       
   219         }
       
   220 
       
   221         $link = $this->_element->createElement('link');
       
   222         $link->setAttribute('rel', 'self');
       
   223         $link->setAttribute('href', $array->link);
       
   224         if (isset($array->language)) {
       
   225             $link->setAttribute('hreflang', $array->language);
       
   226         }
       
   227         $feed->appendChild($link);
       
   228 
       
   229         if (isset($array->description)) {
       
   230             $subtitle = $this->_element->createElement('subtitle');
       
   231             $subtitle->appendChild($this->_element->createCDATASection($array->description));
       
   232             $feed->appendChild($subtitle);
       
   233         }
       
   234 
       
   235         if (isset($array->copyright)) {
       
   236             $copyright = $this->_element->createElement('rights', $array->copyright);
       
   237             $feed->appendChild($copyright);
       
   238         }
       
   239 
       
   240         if (isset($array->image)) {
       
   241             $image = $this->_element->createElement('logo', $array->image);
       
   242             $feed->appendChild($image);
       
   243         }
       
   244 
       
   245         $generator = !empty($array->generator) ? $array->generator : 'Zend_Feed';
       
   246         $generator = $this->_element->createElement('generator', $generator);
       
   247         $feed->appendChild($generator);
       
   248 
       
   249         return $feed;
       
   250     }
       
   251 
       
   252     /**
       
   253      * Generate the entries of the feed when working in write mode
       
   254      *
       
   255      * The following nodes are constructed for each feed entry
       
   256      * <entry>
       
   257      *    <id>url to feed entry</id>
       
   258      *    <title>entry title</title>
       
   259      *    <updated>last update</updated>
       
   260      *    <link rel="alternate" href="url to feed entry" />
       
   261      *    <summary>short text</summary>
       
   262      *    <content>long version, can contain html</content>
       
   263      * </entry>
       
   264      *
       
   265      * @param  array      $array the data to use
       
   266      * @param  DOMElement $root  the root node to use
       
   267      * @return void
       
   268      */
       
   269     protected function _mapFeedEntries(DOMElement $root, $array)
       
   270     {
       
   271         foreach ($array as $dataentry) {
       
   272             $entry = $this->_element->createElement('entry');
       
   273 
       
   274             $id = $this->_element->createElement('id', isset($dataentry->guid) ? $dataentry->guid : $dataentry->link);
       
   275             $entry->appendChild($id);
       
   276 
       
   277             $title = $this->_element->createElement('title');
       
   278             $title->appendChild($this->_element->createCDATASection($dataentry->title));
       
   279             $entry->appendChild($title);
       
   280 
       
   281             $updated = isset($dataentry->lastUpdate) ? $dataentry->lastUpdate : time();
       
   282             $updated = $this->_element->createElement('updated', date(DATE_ATOM, $updated));
       
   283             $entry->appendChild($updated);
       
   284 
       
   285             $link = $this->_element->createElement('link');
       
   286             $link->setAttribute('rel', 'alternate');
       
   287             $link->setAttribute('href', $dataentry->link);
       
   288             $entry->appendChild($link);
       
   289 
       
   290             $summary = $this->_element->createElement('summary');
       
   291             $summary->appendChild($this->_element->createCDATASection($dataentry->description));
       
   292             $entry->appendChild($summary);
       
   293 
       
   294             if (isset($dataentry->content)) {
       
   295                 $content = $this->_element->createElement('content');
       
   296                 $content->setAttribute('type', 'html');
       
   297                 $content->appendChild($this->_element->createCDATASection($dataentry->content));
       
   298                 $entry->appendChild($content);
       
   299             }
       
   300 
       
   301             if (isset($dataentry->category)) {
       
   302                 foreach ($dataentry->category as $category) {
       
   303                     $node = $this->_element->createElement('category');
       
   304                     $node->setAttribute('term', $category['term']);
       
   305                     if (isset($category['scheme'])) {
       
   306                         $node->setAttribute('scheme', $category['scheme']);
       
   307                     }
       
   308                     $entry->appendChild($node);
       
   309                 }
       
   310             }
       
   311 
       
   312             if (isset($dataentry->source)) {
       
   313                 $source = $this->_element->createElement('source');
       
   314                 $title = $this->_element->createElement('title', $dataentry->source['title']);
       
   315                 $source->appendChild($title);
       
   316                 $link = $this->_element->createElement('link', $dataentry->source['title']);
       
   317                 $link->setAttribute('rel', 'alternate');
       
   318                 $link->setAttribute('href', $dataentry->source['url']);
       
   319                 $source->appendChild($link);
       
   320             }
       
   321 
       
   322             if (isset($dataentry->enclosure)) {
       
   323                 foreach ($dataentry->enclosure as $enclosure) {
       
   324                     $node = $this->_element->createElement('link');
       
   325                     $node->setAttribute('rel', 'enclosure');
       
   326                     $node->setAttribute('href', $enclosure['url']);
       
   327                     if (isset($enclosure['type'])) {
       
   328                         $node->setAttribute('type', $enclosure['type']);
       
   329                     }
       
   330                     if (isset($enclosure['length'])) {
       
   331                         $node->setAttribute('length', $enclosure['length']);
       
   332                     }
       
   333                     $entry->appendChild($node);
       
   334                 }
       
   335             }
       
   336 
       
   337             if (isset($dataentry->comments)) {
       
   338                 $comments = $this->_element->createElementNS('http://wellformedweb.org/CommentAPI/',
       
   339                                                              'wfw:comment',
       
   340                                                              $dataentry->comments);
       
   341                 $entry->appendChild($comments);
       
   342             }
       
   343             if (isset($dataentry->commentRss)) {
       
   344                 $comments = $this->_element->createElementNS('http://wellformedweb.org/CommentAPI/',
       
   345                                                              'wfw:commentRss',
       
   346                                                              $dataentry->commentRss);
       
   347                 $entry->appendChild($comments);
       
   348             }
       
   349 
       
   350             $root->appendChild($entry);
       
   351         }
       
   352     }
       
   353 
       
   354     /**
       
   355      * Override Zend_Feed_Element to allow formated feeds
       
   356      *
       
   357      * @return string
       
   358      */
       
   359     public function saveXml()
       
   360     {
       
   361         // Return a complete document including XML prologue.
       
   362         $doc = new DOMDocument($this->_element->ownerDocument->version,
       
   363                                $this->_element->ownerDocument->actualEncoding);
       
   364         $doc->appendChild($doc->importNode($this->_element, true));
       
   365         $doc->formatOutput = true;
       
   366 
       
   367         return $doc->saveXML();
       
   368     }
       
   369 
       
   370     /**
       
   371      * Send feed to a http client with the correct header
       
   372      *
       
   373      * @return void
       
   374      * @throws Zend_Feed_Exception if headers have already been sent
       
   375      */
       
   376     public function send()
       
   377     {
       
   378         if (headers_sent()) {
       
   379             /**
       
   380              * @see Zend_Feed_Exception
       
   381              */
       
   382             require_once 'Zend/Feed/Exception.php';
       
   383             throw new Zend_Feed_Exception('Cannot send ATOM because headers have already been sent.');
       
   384         }
       
   385 
       
   386         header('Content-Type: application/atom+xml; charset=' . $this->_element->ownerDocument->actualEncoding);
       
   387 
       
   388         echo $this->saveXML();
       
   389     }
       
   390 }