Apache Zeta Components Manual :: File Source for atom.php

Source for file atom.php

Documentation is available at atom.php

  1. <?php
  2. /**
  3.  * File containing the ezcFeedAtom class.
  4.  *
  5.  * Licensed to the Apache Software Foundation (ASF) under one
  6.  * or more contributor license agreements.  See the NOTICE file
  7.  * distributed with this work for additional information
  8.  * regarding copyright ownership.  The ASF licenses this file
  9.  * to you under the Apache License, Version 2.0 (the
  10.  * "License"); you may not use this file except in compliance
  11.  * with the License.  You may obtain a copy of the License at
  12.  * 
  13.  *   http://www.apache.org/licenses/LICENSE-2.0
  14.  * 
  15.  * Unless required by applicable law or agreed to in writing,
  16.  * software distributed under the License is distributed on an
  17.  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
  18.  * KIND, either express or implied.  See the License for the
  19.  * specific language governing permissions and limitations
  20.  * under the License.
  21.  *
  22.  * @package Feed
  23.  * @version //autogentag//
  24.  * @license http://www.apache.org/licenses/LICENSE-2.0 Apache License, Version 2.0
  25.  * @filesource
  26.  */
  27.  
  28. /**
  29.  * Class providing parsing and generating of ATOM feeds.
  30.  *
  31.  * Specifications:
  32.  * {@link http://atompub.org/rfc4287.html ATOM RFC4287}.
  33.  *
  34.  * @package Feed
  35.  * @version //autogentag//
  36.  */
  37. class ezcFeedAtom extends ezcFeedProcessor implements ezcFeedParser
  38. {
  39.     /**
  40.      * Defines the feed type of this processor.
  41.      */
  42.     const FEED_TYPE = 'atom';
  43.  
  44.     /**
  45.      * Defines the feed content type of this processor.
  46.      */
  47.     const CONTENT_TYPE = 'application/atom+xml';
  48.  
  49.     /**
  50.      * Defines the namespace for ATOM feeds.
  51.      */
  52.     const NAMESPACE_URI = 'http://www.w3.org/2005/Atom';
  53.  
  54.     /**
  55.      * Creates a new ATOM processor.
  56.      *
  57.      * @param ezcFeed $container The feed data container used when generating
  58.      */
  59.     public function __constructezcFeed $container )
  60.     {
  61.         $this->feedContainer $container;
  62.         $this->feedType self::FEED_TYPE;
  63.         $this->contentType self::CONTENT_TYPE;
  64.     }
  65.  
  66.     /**
  67.      * Returns an XML string from the feed information contained in this
  68.      * processor.
  69.      *
  70.      * @return string 
  71.      */
  72.     public function generate()
  73.     {
  74.         $this->xml new DOMDocument'1.0''utf-8' );
  75.         $this->xml->formatOutput 1;
  76.  
  77.         $rss $this->xml->createElementNSself::NAMESPACE_URI'feed' );
  78.         $this->channel $rss;
  79.         $this->root $this->xml->appendChild$rss );
  80.  
  81.         $this->generateRequired();
  82.         $this->generateAtLeastOne();
  83.         $this->generateOptional();
  84.         $this->generateFeedModules$this->channel );
  85.         $this->generateItems();
  86.  
  87.         return $this->xml->saveXML();
  88.     }
  89.  
  90.     /**
  91.      * Returns true if the parser can parse the provided XML document object,
  92.      * false otherwise.
  93.      *
  94.      * @param DOMDocument $xml The XML document object to check for parseability
  95.      * @return bool 
  96.      */
  97.     public static function canParseDOMDocument $xml )
  98.     {
  99.         if $xml->documentElement->tagName !== 'feed' )
  100.         {
  101.             return false;
  102.         }
  103.  
  104.         return true;
  105.     }
  106.  
  107.     /**
  108.      * Parses the provided XML document object and returns an ezcFeed object
  109.      * from it.
  110.      *
  111.      * @throws ezcFeedParseErrorException
  112.      *          If an error was encountered during parsing.
  113.      *
  114.      * @param DOMDocument $xml The XML document object to parse
  115.      * @return ezcFeed 
  116.      */
  117.     public function parseDOMDocument $xml )
  118.     {
  119.         $feed new ezcFeedself::FEED_TYPE );
  120.         $channel $xml->documentElement;
  121.  
  122.         $this->usedPrefixes $this->fetchUsedPrefixes$xml );
  123.  
  124.         foreach $channel->childNodes as $channelChild )
  125.         {
  126.             if $channelChild->nodeType == XML_ELEMENT_NODE )
  127.             {
  128.                 $tagName $channelChild->tagName;
  129.  
  130.                 switch $tagName )
  131.                 {
  132.                     case 'title':
  133.                         $this->parseTextNode$feed$channelChild'title' );
  134.                         break;
  135.  
  136.                     case 'rights':
  137.                         $this->parseTextNode$feed$channelChild'copyright' );
  138.                         break;
  139.  
  140.                     case 'subtitle':
  141.                         $this->parseTextNode$feed$channelChild'description' );
  142.                         break;
  143.  
  144.                     case 'id':
  145.                         $feed->$tagName $channelChild->textContent;
  146.                         break;
  147.  
  148.                     case 'icon':
  149.                         $feed->$tagName $channelChild->textContent;
  150.                         break;
  151.  
  152.                     case 'logo':
  153.                         $feed->image $channelChild->textContent;
  154.                         break;
  155.  
  156.                     case 'generator':
  157.                         $element $feed->add$tagName );
  158.  
  159.                         $attributes array'uri' => 'url''version' => 'version' );
  160.                         foreach $attributes as $name => $alias )
  161.                         {
  162.                             if $channelChild->hasAttribute$name ) )
  163.                             {
  164.                                 $element->$alias $channelChild->getAttribute$name );
  165.                             }
  166.                         }
  167.                         $element->name $channelChild->textContent;
  168.                         break;
  169.  
  170.                     case 'updated':
  171.                         $feed->$tagName $channelChild->textContent;
  172.                         break;
  173.  
  174.                     case 'category':
  175.                         $element $feed->add$tagName );
  176.  
  177.                         $attributes array'term' => 'term''scheme' => 'scheme''label' => 'label' );
  178.                         foreach $attributes as $name => $alias )
  179.                         {
  180.                             if $channelChild->hasAttribute$name ) )
  181.                             {
  182.                                 $element->$alias $channelChild->getAttribute$name );
  183.                             }
  184.                         }
  185.                         break;
  186.  
  187.                     case 'link':
  188.                         $element $feed->add$tagName );
  189.  
  190.                         $attributes array'href' => 'href''rel' => 'rel''hreflang' => 'hreflang',
  191.                                              'type' => 'type''title' => 'title''length' => 'length' );
  192.  
  193.                         foreach $attributes as $name => $alias )
  194.                         {
  195.                             if $channelChild->hasAttribute$name ) )
  196.                             {
  197.                                 $element->$alias $channelChild->getAttribute$name );
  198.                             }
  199.                         }
  200.                         break;
  201.  
  202.                     case 'contributor':
  203.                     case 'author':
  204.                         $element $feed->add$tagName );
  205.                         $this->parsePerson$element$channelChild$tagName );
  206.                         break;
  207.  
  208.                     case 'entry':
  209.                         $element $feed->add'item' );
  210.                         $this->parseItem$element$channelChild );
  211.                         break;
  212.  
  213.                     default:
  214.                         // check if it's part of a known module/namespace
  215.                         $this->parseModules$feed$channelChild$tagName );
  216.                         break;
  217.                 }
  218.             }
  219.         }
  220.  
  221.         if $channel->hasAttribute'xml:lang' ) )
  222.         {
  223.             $feed->language $channel->getAttribute'xml:lang' );
  224.         }
  225.  
  226.         return $feed;
  227.     }
  228.  
  229.     /**
  230.      * Adds the required feed elements to the XML document being generated.
  231.      */
  232.     private function generateRequired()
  233.     {
  234.         $elements array'id''title''updated' );
  235.         foreach $elements as $element )
  236.         {
  237.             $data $this->$element;
  238.             if is_null$data ) )
  239.             {
  240.                 throw new ezcFeedRequiredMetaDataMissingException"/feed/{$element});
  241.             }
  242.  
  243.             switch $element )
  244.             {
  245.                 case 'id':
  246.                     $this->generateMetaData$this->channel$element$data );
  247.                     break;
  248.  
  249.                 case 'title':
  250.                     $this->generateTextNode$this->channel$element$data );
  251.                     break;
  252.  
  253.                 case 'updated':
  254.                     // Sample date: 2003-12-13T18:30:02-05:00
  255.                     $this->generateMetaData$this->channel$element$data->date->format'c' ) );
  256.                     break;
  257.  
  258.             }
  259.         }
  260.     }
  261.  
  262.     /**
  263.      * Adds the at-least-one feed elements to the XML document being generated.
  264.      */
  265.     private function generateAtLeastOne()
  266.     {
  267.         $needToThrowException false;
  268.         $element 'author';
  269.  
  270.         $data $this->$element;
  271.  
  272.         if is_null$data ) )
  273.         {
  274.             $entries $this->item;
  275.             if $entries === null )
  276.             {
  277.                 throw new ezcFeedAtLeastOneItemDataRequiredExceptionarray'/feed/author' ) );
  278.             }
  279.  
  280.             foreach $entries as $entry )
  281.             {
  282.                 $authors $entry->author;
  283.                 if $authors === null )
  284.                 {
  285.                     throw new ezcFeedAtLeastOneItemDataRequiredExceptionarray'/feed/entry/author' ) );
  286.                 }
  287.             }
  288.  
  289.             throw new ezcFeedAtLeastOneItemDataRequiredExceptionarray'/feed/author' ) );
  290.         }
  291.     }
  292.  
  293.     /**
  294.      * Adds the optional feed elements to the XML document being generated.
  295.      */
  296.     private function generateOptional()
  297.     {
  298.         $elements array'author''link''category',
  299.                            'contributor''generator''icon',
  300.                            'image''copyright''description''language' );
  301.  
  302.         if $this->link !== null )
  303.         {
  304.             $this->checkLinks$this->channel$this->link );
  305.         }
  306.  
  307.         foreach $elements as $element )
  308.         {
  309.             $data $this->$element;
  310.  
  311.             if !is_null$data ) )
  312.             {
  313.                 switch $element )
  314.                 {
  315.                     case 'contributor':
  316.                         foreach $this->contributor as $person )
  317.                         {
  318.                             $this->generatePerson$this->channel'contributor'$person );
  319.                         }
  320.                         break;
  321.  
  322.                     case 'author':
  323.                         foreach $this->author as $person )
  324.                         {
  325.                             $this->generatePerson$this->channel'author'$person );
  326.                         }
  327.                         break;
  328.  
  329.                     case 'generator':
  330.                         $this->generateGenerator$this->channel$this->generator );
  331.                         break;
  332.  
  333.                     case 'link':
  334.                         foreach $data as $dataNode )
  335.                         {
  336.                             $this->generateLink$this->channel$dataNode );
  337.                         }
  338.                         break;
  339.  
  340.                     case 'category':
  341.                         foreach $data as $dataNode )
  342.                         {
  343.                             $this->generateCategory$this->channel$dataNode );
  344.                         }
  345.                         break;
  346.  
  347.                     case 'description':
  348.                         $this->generateTextNode$this->channel'subtitle'$data );
  349.                         break;
  350.  
  351.                     case 'copyright':
  352.                         $this->generateTextNode$this->channel'rights'$data );
  353.                         break;
  354.  
  355.                     case 'image':
  356.                         $this->generateMetaData$this->channel'logo'$data );
  357.                         break;
  358.  
  359.                     case 'icon':
  360.                         $this->generateMetaData$this->channel'icon'$data );
  361.                         break;
  362.                         
  363.                     case 'language':
  364.                         $this->generateLanguage$this->channel$data );
  365.                         break;
  366.                 }
  367.             }
  368.         }
  369.     }
  370.  
  371.     /**
  372.      * Checks if the links are defined correctly.
  373.      *
  374.      * @throws ezcFeedOnlyOneValueAllowedException
  375.      *          if there was more than one @rel="alternate" element in the $links array
  376.      *
  377.      * @param DOMNode $root The root in which to check the link elements
  378.      * @param array(ezcFeedLinkElement) $links The link elements to check
  379.      * @return bool 
  380.      */
  381.     private function checkLinksDOMNode $rootarray $links )
  382.     {
  383.         $unique array();
  384.         foreach $links as $dataNode )
  385.         {
  386.             if ( ( isset$dataNode->rel && $dataNode->rel === 'alternate' )
  387.                  && isset$dataNode->type )
  388.                  && isset$dataNode->hreflang ) )
  389.             {
  390.                 foreach $unique as $obj )
  391.                 {
  392.                     if $obj['type'=== $dataNode->type
  393.                          && $obj['hreflang'=== $dataNode->hreflang )
  394.                     {
  395.                         $parentNode $root->nodeName === 'entry' '/feed' '';
  396.                         $parentNode $root->nodeName === 'source' '/feed/entry' $parentNode;
  397.  
  398.                         throw new ezcFeedOnlyOneValueAllowedException"{$parentNode}/{$root->nodeName}/link@rel=\"alternate\");
  399.                     }
  400.                 }
  401.  
  402.                 $unique[array'type' => $dataNode->type,
  403.                                    'hreflang' => $dataNode->hreflang );
  404.  
  405.             }
  406.         }
  407.  
  408.         return true;
  409.     }
  410.  
  411.     /**
  412.      * Creates a link node in the XML document being generated.
  413.      *
  414.      * @param DOMNode $root The root in which to create the link
  415.      * @param ezcFeedLinkElement $dataNode The data for the link node to create
  416.      */
  417.     private function generateLinkDOMNode $rootezcFeedLinkElement $dataNode )
  418.     {
  419.         $elementTag $this->xml->createElement'link' );
  420.         $root->appendChild$elementTag );
  421.  
  422.         $elements array'href''rel''type''hreflang''title''length' );
  423.         if !isset$dataNode->href ) )
  424.         {
  425.             $parentNode $root->nodeName === 'entry' '/feed' '';
  426.             $parentNode $root->nodeName === 'source' '/feed/entry' $parentNode;
  427.  
  428.             throw new ezcFeedRequiredMetaDataMissingException"{$parentNode}/{$root->nodeName}/link/@href);
  429.         }
  430.  
  431.         foreach $elements as $attribute )
  432.         {
  433.             if isset$dataNode->$attribute ) )
  434.             {
  435.                 $this->addAttribute$elementTag$attribute$dataNode->$attribute );
  436.             }
  437.         }
  438.     }
  439.  
  440.     /**
  441.      * Creates a generator node in the XML document being generated.
  442.      *
  443.      * @param DOMNode $root The root in which to create the generator node
  444.      * @param ezcFeedGeneratorElement $generator The data for the generator node to create
  445.      */
  446.     private function generateGeneratorDOMNode $rootezcFeedGeneratorElement $generator )
  447.     {
  448.         $name $generator->name;
  449.         $version $generator->version;
  450.         $url $generator->url;
  451.  
  452.         $elementTag $this->xml->createElement'generator'$name );
  453.         $root->appendChild$elementTag );
  454.  
  455.         if $version !== null )
  456.         {
  457.             $this->addAttribute$elementTag'version'$version );
  458.         }
  459.  
  460.         if $url !== null )
  461.         {
  462.             $this->addAttribute$elementTag'uri'$url );
  463.         }
  464.     }
  465.  
  466.     /**
  467.      * Creates a category node in the XML document being generated.
  468.      *
  469.      * @throws ezcFeedRequiredMetaDataMissingException
  470.      *          if the required attributes are missing
  471.      *
  472.      * @param DOMNode $root The root in which to create the category node
  473.      * @param ezcFeedCategoryElement $dataNode The data for the category node to create
  474.      */
  475.     private function generateCategoryDOMNode $rootezcFeedCategoryElement $dataNode )
  476.     {
  477.         $elementTag $this->xml->createElement'category' );
  478.         $root->appendChild$elementTag );
  479.  
  480.         $parentNode $root->nodeName === 'entry' '/feed' '';
  481.         $parentNode $root->nodeName === 'source' '/feed/entry' $parentNode;
  482.  
  483.         $attributes array'term' => 'term''scheme' => 'scheme''label' => 'label' );
  484.         $required array'term' );
  485.         $optional array'scheme''label' );
  486.  
  487.         foreach $attributes as $attribute => $alias )
  488.         {
  489.             if isset$dataNode->$alias ) )
  490.             {
  491.                 $val $dataNode->$alias;
  492.                 $this->addAttribute$elementTag$attribute$val );
  493.             }
  494.             else if in_array$attribute$required ) )
  495.             {
  496.                 throw new ezcFeedRequiredMetaDataMissingException"{$parentNode}/{$root->nodeName}/category/@{$attribute});
  497.             }
  498.         }
  499.     }
  500.  
  501.     /**
  502.      * Creates an XML node in the XML document being generated.
  503.      *
  504.      * @param DOMNode $root The root in which to create the node $element
  505.      * @param string $element The name of the node to create
  506.      * @param ezcFeedTextElement $dataNode The data for the node to create
  507.      */
  508.     private function generateTextNodeDOMNode $root$elementezcFeedTextElement $dataNode )
  509.     {
  510.         $elementTag $this->xml->createElement$element );
  511.         $root->appendChild$elementTag );
  512.  
  513.         $attributes array();
  514.  
  515.         if isset$dataNode->type ) )
  516.         {
  517.             $val $dataNode->type;
  518.             switch $val )
  519.             {
  520.                 case 'html':
  521.                     $dataNode->text htmlspecialchars$dataNode->__toString() );
  522.                     $this->addAttribute$elementTag'type'$val );
  523.                     break;
  524.  
  525.                 case 'xhtml':
  526.                     $this->addAttribute$elementTag'type'$val );
  527.                     $this->addAttribute$elementTag'xmlns:xhtml''http://www.w3.org/1999/xhtml' );
  528.                     $xhtmlTag $this->xml->createElement'xhtml:div'$dataNode->__toString() );
  529.                     $elementTag->appendChild$xhtmlTag );
  530.                     $elementTag $xhtmlTag;
  531.                     break;
  532.  
  533.                 case 'text':
  534.                     // same as the default case
  535.  
  536.                 default:
  537.                     $val 'text';
  538.                     $this->addAttribute$elementTag'type'$val );
  539.                     break;
  540.  
  541.             }
  542.         }
  543.  
  544.         if isset$dataNode->language ) )
  545.         {
  546.             if $dataNode->type === 'xhtml' )
  547.             {
  548.                 $this->addAttribute$elementTag->parentNode'xml:lang'$dataNode->language );
  549.             }
  550.             else
  551.             {
  552.                 $this->addAttribute$elementTag'xml:lang'$dataNode->language );
  553.             }
  554.         }
  555.  
  556.         $elementTag->nodeValue $dataNode;
  557.     }
  558.     
  559.     /**
  560.      * Creates an attribute on an XML node containing the language in it.
  561.      *
  562.      * @param DOMNode $root The root in which to create the attribute
  563.      * @param ezcFeedTextElement $dataNode The data for the node to create
  564.      */
  565.     private function generateLanguageDOMNode $rootezcFeedTextElement $dataNode  )
  566.     {
  567.         $this->addAttribute$root'xml:lang'$dataNode->text );
  568.     }
  569.  
  570.     /**
  571.      * Creates an XML node in the XML document being generated.
  572.      *
  573.      * @param DOMNode $root The root in which to create the node $element
  574.      * @param string $element The name of the node to create
  575.      * @param array(string=>mixed) $dataNode The data for the node to create
  576.      */
  577.     private function generateContentNodeDOMNode $root$element$dataNode )
  578.     {
  579.         $elementTag $this->xml->createElement$element );
  580.         $root->appendChild$elementTag );
  581.  
  582.         $attributes array();
  583.  
  584.         if isset$dataNode->type ) )
  585.         {
  586.             $val $dataNode->type;
  587.             switch $val )
  588.             {
  589.                 case 'html':
  590.                     $dataNode->text htmlspecialchars$dataNode->__toString() );
  591.                     $this->addAttribute$elementTag'type'$val );
  592.                     break;
  593.  
  594.                 case 'xhtml':
  595.                     $this->addAttribute$elementTag'type'$val );
  596.                     $this->addAttribute$elementTag'xmlns:xhtml''http://www.w3.org/1999/xhtml' );
  597.                     $xhtmlTag $this->xml->createElement'xhtml:div'$dataNode->__toString() );
  598.                     $elementTag->appendChild$xhtmlTag );
  599.                     $elementTag $xhtmlTag;
  600.                     break;
  601.  
  602.                 case 'text':
  603.                     $this->addAttribute$elementTag'type'$val );
  604.                     break;
  605.  
  606.                 default:
  607.                     if preg_match'@[+/]xml$@'$val !== )
  608.                     {
  609.                         // @todo: implement to assign the text in $dataNode as an XML node into $elementTag
  610.                         $this->addAttribute$elementTag'type'$val );
  611.                     }
  612.                     else if substr_compare$val'text/'05true === )
  613.                     {
  614.                         $dataNode->text htmlspecialchars$dataNode->__toString() );
  615.                         $this->addAttribute$elementTag'type'$val );
  616.                         break;
  617.                     }
  618.                     else if $val !== null )
  619.                     {
  620.                         // @todo: make 76 and "\n" options?
  621.                         $dataNode->text chunk_splitbase64_encode$dataNode->__toString() )76"\n" );
  622.                         $this->addAttribute$elementTag'type'$val );
  623.                     }
  624.                     else
  625.                     {
  626.                         $val 'text';
  627.                         $this->addAttribute$elementTag'type'$val );
  628.                     }
  629.                     break;
  630.  
  631.             }
  632.         }
  633.  
  634.         if $dataNode->src !== null )
  635.         {
  636.             $this->addAttribute$elementTag'src'$dataNode->src );
  637.         }
  638.  
  639.         if $dataNode->language !== null )
  640.         {
  641.             if $dataNode->type === 'xhtml' )
  642.             {
  643.                 $this->addAttribute$elementTag->parentNode'xml:lang'$dataNode->language );
  644.             }
  645.             else
  646.             {
  647.                 $this->addAttribute$elementTag'xml:lang'$dataNode->language );
  648.             }
  649.         }
  650.  
  651.         $elementTag->nodeValue $dataNode;
  652.     }
  653.  
  654.     /**
  655.      * Creates an XML person node in the XML document being generated.
  656.      *
  657.      * @param DOMNode $root The root in which to create the node $element
  658.      * @param string $element The name of the node to create
  659.      * @param ezcFeedPersonElement $feedElement The person feed element (author, contributor)
  660.      */
  661.     private function generatePersonDOMNode $root$elementezcFeedPersonElement $feedElement )
  662.     {
  663.         $elementTag $this->xml->createElement$element );
  664.         $root->appendChild$elementTag );
  665.  
  666.         $parentNode $root->nodeName === 'entry' '/feed' '';
  667.         $parentNode $root->nodeName === 'source' '/feed/entry' $parentNode;
  668.  
  669.         $name $feedElement->name;
  670.         $email $feedElement->email;
  671.         $uri $feedElement->uri;
  672.  
  673.         if !is_null$name ) )
  674.         {
  675.             $this->generateMetaData$elementTag'name'$name );
  676.         }
  677.         else
  678.         {
  679.             throw new ezcFeedRequiredMetaDataMissingException"{$parentNode}/{$root->nodeName}/{$element}/name);
  680.         }
  681.  
  682.         if !is_null$email ) )
  683.         {
  684.             $this->generateMetaData$elementTag'email'$email );
  685.         }
  686.  
  687.         if !is_null$uri ) )
  688.         {
  689.             $this->generateMetaData$elementTag'uri'$uri );
  690.         }
  691.     }
  692.  
  693.     /**
  694.      * Creates an XML source node in the XML document being generated.
  695.      *
  696.      * @param DOMNode $root The root in which to create the source node
  697.      * @param ezcFeedSourceElement $feedElement The feed source
  698.      */
  699.     private function generateSourceDOMNode $rootezcFeedSourceElement $feedElement )
  700.     {
  701.         $elementTag $this->xml->createElement'source' );
  702.         $root->appendChild$elementTag );
  703.  
  704.         $elements array'id''title''updated',
  705.                            'author''link''category',
  706.                            'contributor''generator''icon',
  707.                            'image''copyright''description' );
  708.  
  709.         foreach $elements as $child )
  710.         {
  711.             $data $feedElement->$child;
  712.  
  713.             if !is_null$data ) )
  714.             {
  715.                 switch $child )
  716.                 {
  717.                     case 'title':
  718.                         $this->generateTextNode$elementTag'title'$data );
  719.                         break;
  720.  
  721.                     case 'description':
  722.                         $this->generateTextNode$elementTag'subtitle'$data );
  723.                         break;
  724.  
  725.                     case 'copyright':
  726.                         $this->generateTextNode$elementTag'rights'$data );
  727.                         break;
  728.  
  729.                     case 'contributor':
  730.                         foreach $data as $dataNode )
  731.                         {
  732.                             $this->generatePerson$elementTag'contributor'$dataNode );
  733.                         }
  734.                         break;
  735.  
  736.                     case 'author':
  737.                         foreach $data as $dataNode )
  738.                         {
  739.                             $this->generatePerson$elementTag'author'$dataNode );
  740.                         }
  741.                         break;
  742.  
  743.                     case 'generator':
  744.                         $this->generateGenerator$elementTag$data );
  745.                         break;
  746.  
  747.                     case 'link':
  748.                         foreach $data as $dataNode )
  749.                         {
  750.                             $this->generateLink$elementTag$dataNode );
  751.                         }
  752.                         break;
  753.  
  754.                     case 'category':
  755.                         foreach $data as $dataNode )
  756.                         {
  757.                             $this->generateCategory$elementTag$dataNode );
  758.                         }
  759.                         break;
  760.  
  761.                     case 'image':
  762.                         $this->generateMetaData$elementTag'logo'$data );
  763.                         break;
  764.  
  765.                     case 'icon':
  766.                         $this->generateMetaData$elementTag'icon'$data );
  767.                         break;
  768.  
  769.                     case 'updated':
  770.                         // Sample date: 2003-12-13T18:30:02-05:00
  771.                         $this->generateMetaData$elementTag'updated'$data->date->format'c' ) );
  772.                         break;
  773.  
  774.                     case 'id':
  775.                         $this->generateMetaData$elementTag'id'$data );
  776.                         break;
  777.                 }
  778.             }
  779.         }
  780.     }
  781.  
  782.     /**
  783.      * Adds the feed entry elements to the XML document being generated.
  784.      *
  785.      * @throws ezcFeedRequiredMetaDataException
  786.      *          if the required elements or attributes are not present
  787.      */
  788.     private function generateItems()
  789.     {
  790.         $entries $this->item;
  791.         if $entries === null )
  792.         {
  793.             return;
  794.         }
  795.  
  796.         foreach $entries as $entry )
  797.         {
  798.             $entryTag $this->xml->createElement'entry' );
  799.             $this->channel->appendChild$entryTag );
  800.             
  801.             if !is_null$entry->language ) )
  802.             {
  803.                 $this->addAttribute$entryTag'xml:lang'$entry->language );
  804.             }
  805.  
  806.             $elements array'id''title''updated' );
  807.  
  808.             foreach $elements as $element )
  809.             {
  810.                 $data $entry->$element;
  811.  
  812.                 if is_null$data ) )
  813.                 {
  814.                     throw new ezcFeedRequiredMetaDataMissingException"/feed/entry/{$element});
  815.                 }
  816.  
  817.                 switch $element )
  818.                 {
  819.                     case 'id':
  820.                         $this->generateMetaData$entryTag$element$data );
  821.                         break;
  822.  
  823.                     case 'title':
  824.                         $this->generateTextNode$entryTag$element$data );
  825.                         break;
  826.  
  827.                     case 'updated':
  828.                         // Sample date: 2003-12-13T18:30:02-05:00
  829.                         $this->generateMetaData$entryTag$element$data->date->format'c' ) );
  830.                         break;
  831.                 }
  832.             }
  833.  
  834.             // ensure the ATOM rules are applied
  835.             $content $entry->content;
  836.             $summary $entry->description;
  837.             $links $entry->link;
  838.             $contentPresent !is_null$content );
  839.             $contentSrcPresent $contentPresent && is_object$content && !is_null$content->src );
  840.             $contentBase64 true;
  841.             if $contentPresent && is_object$content )
  842.                  && in_array$content->typearray'text''html''xhtml'null ) )
  843.                       || preg_match'@[+/]xml$@i'$content->type !== 0
  844.                       || substr_compare$content->type'text/'05true === ) )
  845.             {
  846.                 $contentBase64 false;
  847.             }
  848.  
  849.             $summaryPresent !is_null$summary );
  850.             $linkAlternatePresent false;
  851.             if $links !== null )
  852.             {
  853.                 foreach $links as $link )
  854.                 {
  855.                     // if the rel attribute is not set or if it is "alternate"
  856.                     // then there is at least one rel="alternate" link in the feed entry
  857.                     if !isset$link->rel )
  858.                          || $link->rel === 'alternate' )
  859.                     {
  860.                         $linkAlternatePresent true;
  861.                         break;
  862.                     }
  863.                 }
  864.             }
  865.  
  866.             if !$contentPresent )
  867.             {
  868.                 if !$linkAlternatePresent && !$summaryPresent )
  869.                 {
  870.                     throw new ezcFeedRequiredMetaDataMissingException'/feed/entry/content' );
  871.                 }
  872.  
  873.                 if !$linkAlternatePresent )
  874.                 {
  875.                     throw new ezcFeedRequiredMetaDataMissingException'/feed/entry/link@rel="alternate"' );
  876.                 }
  877.  
  878.                 if !$summaryPresent )
  879.                 {
  880.                     throw new ezcFeedRequiredMetaDataMissingException'/feed/entry/summary' );
  881.                 }
  882.             }
  883.  
  884.             if $contentPresent )
  885.             {
  886.                 if ( ( $contentSrcPresent || $contentBase64 && !$summaryPresent )
  887.                 {
  888.                     throw new ezcFeedRequiredMetaDataMissingException'/feed/entry/summary' );
  889.                 }
  890.             }
  891.  
  892.             $elements array'author''content''link''description',
  893.                                'category''contributor''published''copyright',
  894.                                'source''enclosure' );
  895.  
  896.             if $entry->link !== null )
  897.             {
  898.                 $this->checkLinks$entryTag$entry->link );
  899.             }
  900.  
  901.             foreach $elements as $element )
  902.             {
  903.                 $data $entry->$element;
  904.  
  905.                 if is_null$data ) )
  906.                 {
  907.                     continue;
  908.                 }
  909.  
  910.                 switch $element )
  911.                 {
  912.                     case 'description':
  913.                         $this->generateTextNode$entryTag'summary'$data );
  914.                         break;
  915.  
  916.                     case 'copyright':
  917.                         $this->generateTextNode$entryTag'rights'$data );
  918.                         break;
  919.  
  920.                     case 'content':
  921.                         $this->generateContentNode$entryTag$element$data );
  922.                         break;
  923.  
  924.                     case 'author':
  925.                     case 'contributor':
  926.                         foreach $data as $dataNode )
  927.                         {
  928.                             $this->generatePerson$entryTag$element$dataNode );
  929.                         }
  930.                         break;
  931.  
  932.                     case 'link':
  933.                         foreach $data as $dataNode )
  934.                         {
  935.                             $this->generateLink$entryTag$dataNode );
  936.                         }
  937.                         break;
  938.  
  939.                     case 'published':
  940.                         // Sample date: 2003-12-13T18:30:02-05:00
  941.                         $this->generateMetaData$entryTag$element$data->date->format'c' ) );
  942.                         break;
  943.  
  944.                     case 'category':
  945.                         foreach $data as $dataNode )
  946.                         {
  947.                             $this->generateCategory$entryTag$dataNode );
  948.                         }
  949.                         break;
  950.  
  951.                     case 'source':
  952.                         $this->generateSource$entryTag$data );
  953.                         break;
  954.  
  955.                     case 'enclosure':
  956.                         // convert RSS2 enclosure elements in ATOM link elements
  957.                         foreach $data as $dataNode )
  958.                         {
  959.                             $link new ezcFeedLinkElement();
  960.                             $link->href $dataNode->url;
  961.                             $link->length $dataNode->length;
  962.                             $link->type $dataNode->type;
  963.                             $link->rel 'enclosure';
  964.  
  965.                             $this->generateLink$entryTag$link );
  966.                         }
  967.                         break;
  968.                 }
  969.             }
  970.  
  971.             $this->generateItemModules$entry$entryTag );
  972.         }
  973.     }
  974.  
  975.     /**
  976.      * Parses the provided XML element object and stores it as a feed item in
  977.      * the provided ezcFeed object.
  978.      *
  979.      * @param ezcFeedEntryElement $element The feed element object that will contain the feed item
  980.      * @param DOMElement $xml The XML element object to parse
  981.      */
  982.     private function parseItemezcFeedEntryElement $elementDOMElement $xml )
  983.     {
  984.         foreach $xml->childNodes as $itemChild )
  985.         {
  986.             if $itemChild->nodeType === XML_ELEMENT_NODE )
  987.             {
  988.                 $tagName $itemChild->tagName;
  989.  
  990.                 switch $tagName )
  991.                 {
  992.                     case 'id':
  993.                         $element->$tagName $itemChild->textContent;
  994.                         break;
  995.  
  996.                     case 'title':
  997.                         $this->parseTextNode$element$itemChild'title' );
  998.                         break;
  999.  
  1000.                     case 'rights':
  1001.                         $this->parseTextNode$element$itemChild'copyright' );
  1002.                         break;
  1003.  
  1004.                     case 'summary':
  1005.                         $this->parseTextNode$element$itemChild'description' );
  1006.                         break;
  1007.  
  1008.                     case 'updated':
  1009.                     case 'published':
  1010.                         $element->$tagName $itemChild->textContent;
  1011.                         break;
  1012.  
  1013.                     case 'author':
  1014.                     case 'contributor':
  1015.                         $subElement $element->add$tagName );
  1016.                         foreach $itemChild->childNodes as $subChild )
  1017.                         {
  1018.                             if $subChild->nodeType === XML_ELEMENT_NODE )
  1019.                             {
  1020.                                 $subTagName $subChild->tagName;
  1021.                                 if in_array$subTagNamearray'name''email''uri' ) ) )
  1022.                                 {
  1023.                                     $subElement->$subTagName $subChild->textContent;
  1024.                                 }
  1025.                             }
  1026.                         }
  1027.                         break;
  1028.  
  1029.                     case 'content':
  1030.                         $type $itemChild->getAttribute'type' );
  1031.                         $src $itemChild->getAttribute'src' );
  1032.                         $subElement $element->add$tagName );
  1033.  
  1034.                         switch $type )
  1035.                         {
  1036.                             case 'xhtml':
  1037.                                 $nodes $itemChild->childNodes;
  1038.                                 if $nodes instanceof DOMNodeList )
  1039.                                 {
  1040.                                     for $i 0$i $nodes->length$i++ )
  1041.                                     {
  1042.                                         if $nodes->item$i instanceof DOMElement )
  1043.                                         {
  1044.                                             break;
  1045.                                         }
  1046.                                     }
  1047.  
  1048.                                     $contentNode $nodes->item$i );
  1049.                                     $subElement->text $contentNode->nodeValue;
  1050.                                 }
  1051.                                 $subElement->type $type;
  1052.                                 break;
  1053.  
  1054.                             case 'html':
  1055.                                 $subElement->text $itemChild->textContent;
  1056.                                 $subElement->type $type;
  1057.                                 break;
  1058.  
  1059.                             case 'text':
  1060.                                 $subElement->text $itemChild->textContent;
  1061.                                 $subElement->type $type;
  1062.                                 break;
  1063.  
  1064.                             case null:
  1065.                                 $subElement->text $itemChild->textContent;
  1066.                                 break;
  1067.  
  1068.                             default:
  1069.                                 if preg_match'@[+/]xml$@i'$type !== )
  1070.                                 {
  1071.                                     foreach $itemChild->childNodes as $node )
  1072.                                     {
  1073.                                         if $node->nodeType === XML_ELEMENT_NODE )
  1074.                                         {
  1075.                                             $doc new DOMDocument'1.0''UTF-8' );
  1076.                                             $copyNode $doc->importNode$nodetrue );
  1077.                                             $doc->appendChild$copyNode );
  1078.                                             $subElement->text $doc->saveXML();
  1079.                                             $subElement->type $type;
  1080.                                             break;
  1081.                                         }
  1082.                                     }
  1083.                                 }
  1084.                                 else if substr_compare$type'text/'05true === )
  1085.                                 {
  1086.                                     $subElement->text $itemChild->textContent;
  1087.                                     $subElement->type $type;
  1088.                                     break;
  1089.                                 }
  1090.                                 else // base64
  1091.                                 {
  1092.                                     $subElement->text base64_decode$itemChild->textContent );
  1093.                                     $subElement->type $type;
  1094.                                 }
  1095.                                 break;
  1096.                         }
  1097.  
  1098.                         if !empty$src ) )
  1099.                         {
  1100.                             $subElement->src $src;
  1101.                         }
  1102.  
  1103.                         $language $itemChild->getAttribute'xml:lang' );
  1104.                         if !empty$language ) )
  1105.                         {
  1106.                             $subElement->language $language;
  1107.                         }
  1108.  
  1109.                         break;
  1110.  
  1111.                     case 'link':
  1112.                         $subElement $element->add$tagName );
  1113.  
  1114.                         $attributes array'href' => 'href''rel' => 'rel''hreflang' => 'hreflang',
  1115.                                              'type' => 'type''title' => 'title''length' => 'length' );
  1116.  
  1117.                         foreach $attributes as $name => $alias )
  1118.                         {
  1119.                             if $itemChild->hasAttribute$name ) )
  1120.                             {
  1121.                                 $subElement->$alias $itemChild->getAttribute$name );
  1122.                             }
  1123.                         }
  1124.                         break;
  1125.  
  1126.                     case 'category':
  1127.                         $subElement $element->add$tagName );
  1128.  
  1129.                         $attributes array'term' => 'term''scheme' => 'scheme''label' => 'label' );
  1130.                         foreach $attributes as $name => $alias )
  1131.                         {
  1132.                             if $itemChild->hasAttribute$name ) )
  1133.                             {
  1134.                                 $subElement->$alias $itemChild->getAttribute$name );
  1135.                             }
  1136.                         }
  1137.                         break;
  1138.  
  1139.                     case 'source':
  1140.                         $subElement $element->add$tagName );
  1141.                         $this->parseSource$subElement$itemChild );
  1142.                         break;
  1143.  
  1144.                     default:
  1145.                         $this->parseModules$element$itemChild$tagName );
  1146.                         break;
  1147.                 }
  1148.             }
  1149.         }
  1150.  
  1151.         if $xml->hasAttribute'xml:lang' ) )
  1152.         {
  1153.             $element->language $xml->getAttribute'xml:lang' );
  1154.         }
  1155.     }
  1156.  
  1157.     /**
  1158.      * Parses the provided XML element object $xml and stores it as a text element
  1159.      *
  1160.      * @param ezcFeed|ezcFeedEntryElement$feed The feed object in which to store the parsed XML element as a text element
  1161.      * @param DOMElement $xml The XML element object to parse
  1162.      * @param string $element The name of the feed element object that will contain the text
  1163.      */
  1164.     private function parseTextNode$feedDOMElement $xml$element )
  1165.     {
  1166.         $type $xml->getAttribute'type' );
  1167.  
  1168.         switch $type )
  1169.         {
  1170.             case 'xhtml':
  1171.                 $nodes $xml->childNodes;
  1172.                 if $nodes instanceof DOMNodeList )
  1173.                 {
  1174.                     $contentNode $nodes->item);
  1175.                     $feed->$element $contentNode->nodeValue;
  1176.                 }
  1177.                 break;
  1178.  
  1179.             case 'html':
  1180.                 $feed->$element $xml->nodeValue;
  1181.                 break;
  1182.  
  1183.             case 'text':
  1184.                 // same case as 'default'
  1185.  
  1186.             default:
  1187.                 $feed->$element $xml->nodeValue;
  1188.                 break;
  1189.         }
  1190.  
  1191.         if $type !== '' )
  1192.         {
  1193.             $feed->$element->type $type;
  1194.         }
  1195.  
  1196.         if $xml->hasAttribute'xml:lang' ) )
  1197.         {
  1198.             $feed->$element->language $xml->getAttribute'xml:lang' );
  1199.         }
  1200.     }
  1201.  
  1202.     /**
  1203.      * Parses the provided XML element object and stores it as a feed person (author
  1204.      * or contributor - based on $type) in the provided ezcFeedPersonElement object.
  1205.      *
  1206.      * @param ezcFeedPersonElement $element The feed element object that will contain the feed person
  1207.      * @param DOMElement $xml The XML element object to parse
  1208.      * @param string $type The type of the person (author, contributor)
  1209.      */
  1210.     private function parsePerson$elementDOMElement $xml$type )
  1211.     {
  1212.         foreach $xml->childNodes as $itemChild )
  1213.         {
  1214.             if $itemChild->nodeType === XML_ELEMENT_NODE )
  1215.             {
  1216.                 $tagName $itemChild->tagName;
  1217.  
  1218.                 switch $tagName )
  1219.                 {
  1220.                     case 'name':
  1221.                     case 'email':
  1222.                     case 'uri':
  1223.                         $element->$tagName $itemChild->textContent;
  1224.                         break;
  1225.                 }
  1226.             }
  1227.         }
  1228.     }
  1229.  
  1230.     /**
  1231.      * Parses the provided XML element object and stores it as a feed source
  1232.      * element in the provided ezcFeedSourceElement object.
  1233.      *
  1234.      * @param ezcFeedSourceElement $element The feed element object that will contain the feed source
  1235.      * @param DOMElement $xml The XML element object to parse
  1236.      */
  1237.     private function parseSourceezcFeedSourceElement $elementDOMElement $xml )
  1238.     {
  1239.         foreach $xml->childNodes as $sourceChild )
  1240.         {
  1241.             if $sourceChild->nodeType === XML_ELEMENT_NODE )
  1242.             {
  1243.                 $tagName $sourceChild->tagName;
  1244.  
  1245.                 switch $tagName )
  1246.                 {
  1247.                     case 'title':
  1248.                         $this->parseTextNode$element$sourceChild'title' );
  1249.                         break;
  1250.  
  1251.                     case 'rights':
  1252.                         $this->parseTextNode$element$sourceChild'copyright' );
  1253.                         break;
  1254.  
  1255.                     case 'subtitle':
  1256.                         $this->parseTextNode$element$sourceChild'description' );
  1257.                         break;
  1258.  
  1259.                     case 'id':
  1260.                         $subElement $element->add'id' );
  1261.                         $subElement->id $sourceChild->textContent;
  1262.                         break;
  1263.  
  1264.                     case 'generator':
  1265.                         $subElement $element->add'generator' );
  1266.                         $subElement->name $sourceChild->textContent;
  1267.  
  1268.                         $attributes array'uri' => 'url''version' => 'version' );
  1269.                         foreach $attributes as $name => $alias )
  1270.                         {
  1271.                             if $sourceChild->hasAttribute$name ) )
  1272.                             {
  1273.                                 $subElement->$alias $sourceChild->getAttribute$name );
  1274.                             }
  1275.                         }
  1276.                         break;
  1277.  
  1278.                     case 'logo':
  1279.                         $subElement $element->add'image' );
  1280.                         $subElement->link = $sourceChild->textContent;
  1281.                         break;
  1282.  
  1283.                     case 'icon':
  1284.                         $subElement $element->add'icon' );
  1285.                         $subElement->link = $sourceChild->textContent;
  1286.                         break;
  1287.  
  1288.                     case 'updated':
  1289.                         $element->$tagName $sourceChild->textContent;
  1290.                         break;
  1291.  
  1292.                     case 'category':
  1293.                         $subElement $element->add$tagName );
  1294.  
  1295.                         $attributes array'term' => 'term''scheme' => 'scheme''label' => 'label' );
  1296.                         foreach $attributes as $name => $alias )
  1297.                         {
  1298.                             if $sourceChild->hasAttribute$name ) )
  1299.                             {
  1300.                                 $subElement->$alias $sourceChild->getAttribute$name );
  1301.                             }
  1302.                         }
  1303.                         break;
  1304.  
  1305.                     case 'link':
  1306.                         $subElement $element->add$tagName );
  1307.  
  1308.                         $attributes array'href' => 'href''rel' => 'rel''hreflang' => 'hreflang',
  1309.                                              'type' => 'type''title' => 'title''length' => 'length' );
  1310.  
  1311.                         foreach $attributes as $name => $alias )
  1312.                         {
  1313.                             if $sourceChild->hasAttribute$name ) )
  1314.                             {
  1315.                                 $subElement->$alias $sourceChild->getAttribute$name );
  1316.                             }
  1317.                         }
  1318.                         break;
  1319.  
  1320.                     case 'contributor':
  1321.                     case 'author':
  1322.                         $subElement $element->add$tagName );
  1323.                         $this->parsePerson$subElement$sourceChild$tagName );
  1324.                         break;
  1325.                 }
  1326.             }
  1327.         }
  1328.     }
  1329. }
  1330. ?>
Documentation generated by phpDocumentor 1.4.3