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

Source for file feed.php

Documentation is available at feed.php

  1. <?php
  2. /**
  3.  * File containing the ezcFeed 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 defining a feed.
  30.  *
  31.  * A feed has a type (eg. RSS1, RSS2 or ATOM). The feed type defines which
  32.  * processor is used to parse and generate that type.
  33.  *
  34.  * The following feed processors are supported by the Feed component:
  35.  *  - ATOM ({@link ezcFeedAtom}) -
  36.  *    {@link http://atompub.org/rfc4287.html RFC4287}
  37.  *  - RSS1 ({@link ezcFeedRss1}) -
  38.  *    {@link http://web.resource.org/rss/1.0/spec Specifications}
  39.  *  - RSS2 ({@link ezcFeedRss2}) -
  40.  *    {@link http://www.rssboard.org/rss-specification Specifications}
  41.  *
  42.  * A new processor can be defined by creating a class which extends the class
  43.  * {@link ezcFeedProcessor} and implements the interface {@link ezcFeedParser}.
  44.  * The new class needs to be added to the supported feed types list by calling
  45.  * the function {@link registerFeed}.
  46.  *
  47.  * The following modules are supported by the Feed component:
  48.  *  - Content ({@link ezcFeedContentModule}) -
  49.  *    {@link http://purl.org/rss/1.0/modules/content/ Specifications}
  50.  *  - CreativeCommons ({@link ezcFeedCreativeCommonsModule}) -
  51.  *    {@link http://backend.userland.com/creativeCommonsRssModule Specifications}
  52.  *  - DublinCore ({@link ezcFeedDublinCoreModule}) -
  53.  *    {@link http://dublincore.org/documents/dces/ Specifications}
  54.  *  - Geo ({@link ezcFeedGeoModule}) -
  55.  *    {@link http://www.w3.org/2003/01/geo/ Specifications}
  56.  *  - GeoRss ({@link ezcFeedGeoRssModule}) -
  57.  *    {@link http://www.georss.org/georss/ Specifications}
  58.  *  - iTunes ({@link ezcFeedITunesModule}) -
  59.  *    {@link http://www.apple.com/itunes/store/podcaststechspecs.html Specifications}
  60.  *
  61.  * A new module can be defined by creating a class which extends the class
  62.  * {@link ezcFeedModule}. The new class needs to be added to the supported modules
  63.  * list by calling {@link registerModule}.
  64.  *
  65.  * A feed object can be created in different ways:
  66.  *  - by calling the constructor (with the optional feed type). Example:
  67.  *
  68.  *  <code>
  69.  *  $feed = new ezcFeed();
  70.  *  </code>
  71.  *
  72.  *  - by parsing an existing XML file or URL. The feed type of the resulting
  73.  *    ezcFeed object will be autodetected. Example:
  74.  *
  75.  *  <code>
  76.  *  $feed = ezcFeed::parse( 'http://www.example.com/rss2.xml' ); // URL
  77.  *  $feed = ezcFeed::parse( 'http://username:password@www.example.com/rss2.xml' ); // URL with HTTP authentication
  78.  *  $feed = ezcFeed::parse( '/tmp/rss2.xml' ); // local file
  79.  *  </code>
  80.  *
  81.  *  - by parsing an XML document stored in a string variable. The feed type of
  82.  *    the resulting ezcFeed object will be autodetected. Example:
  83.  *
  84.  *  <code>
  85.  *  $feed = ezcFeed::parseContent( $xmlString );
  86.  *  </code>
  87.  *
  88.  * Parsing a feed (in the following examples $feed is an existing ezcFeed object):
  89.  * - get a value from the feed object. Example:
  90.  *
  91.  * <code>
  92.  * $title = $feed->title->__toString();
  93.  * </code>
  94.  *
  95.  * - iterate over the items in the feed. Example:
  96.  *
  97.  * <code>
  98.  * <?php
  99.  * // retrieve the titles from the feed items
  100.  * foreach ( $feed->item as $item )
  101.  * {
  102.  *     $titles[] = $item->title->__toString();
  103.  * }
  104.  * </code>
  105.  *
  106.  * - parse a module. Example of parsing the Geo module (ezcFeedGeoModule):
  107.  *
  108.  * <code>
  109.  * <?php
  110.  * $locations = array();
  111.  * foreach ( $feed->item as $item )
  112.  * {
  113.  *     if ( isset( $item->Geo ) )
  114.  *     {
  115.  *         $locations[] = array(
  116.  *             'title' => $item->title->__toString(),
  117.  *             'alt' => isset( $item->Geo->alt ) ? $item->Geo->alt->__toString() : null,
  118.  *             'lat' => isset( $item->Geo->lat ) ? $item->Geo->lat->__toString() : null,
  119.  *             'long' => isset( $item->Geo->long ) ? $item->Geo->long->__toString() : null
  120.  *             );
  121.  *     }
  122.  * }
  123.  * ?>
  124.  * </code>
  125.  *
  126.  * - iterate over the loaded modules in a feed item. Example:
  127.  *
  128.  * <code>
  129.  * <?php
  130.  * // display the names and namespaces of the modules loaded in the feed item $item
  131.  * foreach ( $item->getModules() as $moduleName => $module )
  132.  * {
  133.  *     echo $moduleName . ':' . $module->getNamespace();
  134.  * }
  135.  * ?>
  136.  * </code>
  137.  *
  138.  * Generating a feed:
  139.  * - create a feed object. Example:
  140.  *
  141.  * <code>
  142.  * $feed = new ezcFeed();
  143.  * </code>
  144.  *
  145.  * - set a value to the feed object. Example:
  146.  *
  147.  * <code>
  148.  * $feed->title = 'News';
  149.  * </code>
  150.  *
  151.  * - add a new item to the feed. Example:
  152.  *
  153.  * <code>
  154.  * <?php
  155.  * $item = $feed->add( 'item' );
  156.  * $item->title = 'Item title';
  157.  * ?>
  158.  * </code>
  159.  *
  160.  * - add a new module to the feed item. Example:
  161.  *
  162.  * <code>
  163.  * <?php
  164.  * $item = $feed->add( 'item' );
  165.  * $module = $item->addModule( 'Content' );
  166.  * $content->encoded = 'text content which will be encoded';
  167.  * ?>
  168.  * </code>
  169.  *
  170.  * - generate an XML document from the {@link ezcFeed} object. The result
  171.  *   string should be saved to a file, and a link to a file made accessible
  172.  *   to users of the application. Example:
  173.  *
  174.  * <code>
  175.  * <?php
  176.  * $xmlAtom = $feed->generate( 'atom' );
  177.  * $xmlRss1 = $feed->generate( 'rss1' );
  178.  * $xmlRss2 = $feed->generate( 'rss2' );
  179.  * ?>
  180.  * </code>
  181.  *
  182.  * Note: Assigning values to feed elements should be done in a way that will not
  183.  * break the resulting XML document. In other words, encoding of special characters
  184.  * to HTML entities is not done by default, and the developer is responsible with
  185.  * calling htmlentities() himself when assigning values to feed elements. Example:
  186.  * if the feed title contains the "&" character, it is the responsability of the
  187.  * developer to encode it properly as "&amp;".
  188.  *
  189.  * Example of creating a feed with a user-defined type:
  190.  *
  191.  * <code>
  192.  * <?php
  193.  * ezcFeed::registerFeed( 'opml', 'myOpmlHandler');
  194.  *
  195.  * $feed = new ezcFeed();
  196.  * // add properties to $feed
  197.  *
  198.  * $xml = $feed->generate( 'opml' );
  199.  * ?>
  200.  * </code>
  201.  *
  202.  * In the above example, myOpmlHandler extends {@link ezcFeedProcessor} and
  203.  * implements {@link ezcFeedParser}.
  204.  *
  205.  * Example of creating a feed with a user-defined module:
  206.  *
  207.  * <code>
  208.  * <?php
  209.  * ezcFeed::registerModule( 'Slash', 'mySlashHandler', 'slash');
  210.  *
  211.  * $feed = new ezcFeed();
  212.  * $item = $feed->add( 'item' );
  213.  * $slash = $item->addModule( 'Slash' );
  214.  * // add properties for the Slash module to $slash
  215.  *
  216.  * $xml = $feed->generate( 'rss2' ); // or the feed type which is needed
  217.  * ?>
  218.  * </code>
  219.  *
  220.  * In the above example mySlashHandler extends {@link ezcFeedModule}.
  221.  *
  222.  * @property array(ezcFeedPersonElement) $author 
  223.  *            Author(s) of the feed. Equivalents:
  224.  *            ATOM-author (required, multiple),
  225.  *            RSS1-none,
  226.  *            RSS2-managingEditor (optional, recommended, single).
  227.  * @property array(ezcFeedCategoryElement) $category 
  228.  *            Categories for the feed. Equivalents:
  229.  *            ATOM-category (optional, multiple),
  230.  *            RSS1-none,
  231.  *            RSS2-category (optional, multiple).
  232.  * @property ezcFeedCloudElement $cloud 
  233.  *            Allows processes to register with a cloud to be notified of updates
  234.  *            to the channel, implementing a lightweight publish-subscribe
  235.  *            protocol for RSS feeds. Equivalents:
  236.  *            ATOM-none,
  237.  *            RSS1-none,
  238.  *            RSS2-cloud (optional, not recommended, single).
  239.  * @property array(ezcFeedPersonElement) $contributor 
  240.  *            Contributor(s) for the feed. Equivalents:
  241.  *            ATOM-contributor (optional, not recommended, multiple),
  242.  *            RSS1-none,
  243.  *            RSS2-none.
  244.  * @property ezcFeedTextElement $copyright 
  245.  *            Copyright information for the feed. Equivalents:
  246.  *            ATOM-rights (optional, single),
  247.  *            RSS1-none,
  248.  *            RSS2-copyright (optional, single).
  249.  * @property ezcFeedTextElement $description 
  250.  *            A short description of the feed. Equivalents:
  251.  *            ATOM-subtitle (required, single),
  252.  *            RSS1-description (required, single),
  253.  *            RSS2-description (required, single).
  254.  * @property ezcFeedTextElement $docs 
  255.  *            An URL that points to the documentation for the format used in the
  256.  *            feed file. Equivalents:
  257.  *            ATOM-none,
  258.  *            RSS1-none,
  259.  *            RSS2-docs (optional, not recommended, single) - usual value is
  260.  *            {@link http://www.rssboard.org/rss-specification}.
  261.  * @property ezcFeedGeneratorElement $generator 
  262.  *            Indicates the software used to generate the feed. Equivalents:
  263.  *            ATOM-generator (optional, single),
  264.  *            RSS1-none,
  265.  *            RSS2-generator (optional, single).
  266.  * @property ezcFeedImageElement $icon 
  267.  *            An icon for a feed, similar with favicon.ico for websites. Equivalents:
  268.  *            ATOM-icon (optional, not recommended, single),
  269.  *            RSS1-none,
  270.  *            RSS2-none.
  271.  * @property ezcFeedIdElement $id 
  272.  *            A universally unique and permanent identifier for a feed. For
  273.  *            example, it can be an Internet domain name. Equivalents:
  274.  *            ATOM-id (required, single),
  275.  *            RSS1-about (required, single),
  276.  *            RSS2-id (optional, single).
  277.  * @property ezcFeedImageElement $image 
  278.  *            An image associated with the feed. Equivalents:
  279.  *            ATOM-logo (optional, single),
  280.  *            RSS1-image (optional, single),
  281.  *            RSS2-image (optional, single).
  282.  * @property-read array(ezcFeedEntryElement) $item 
  283.  *            Feed items (entries). Equivalents:
  284.  *            ATOM-entry (optional, recommended, multiple),
  285.  *            RSS1-item (required, multiple),
  286.  *            RSS2-item (required, multiple).
  287.  * @property ezcFeedTextElement $language 
  288.  *            The language for the feed. Equivalents:
  289.  *            ATOM-xml:lang attribute for title, description, copyright, content,
  290.  *            comments (optional, single) - accessed as language through ezcFeed,
  291.  *            RSS1-none,
  292.  *            RSS2-language (optional, single).
  293.  * @property array(ezcFeedLinkElement) $link 
  294.  *            URLs to the HTML websites corresponding to the channel. Equivalents:
  295.  *            ATOM-link (required one link with rel='self', multiple),
  296.  *            RSS1-link (required, single),
  297.  *            RSS2-link (required, single).
  298.  * @property ezcFeedDateElement $published 
  299.  *            The time the feed was published. Equivalents:
  300.  *            ATOM-none,
  301.  *            RSS1-none,
  302.  *            RSS2-pubDate (optional, not recommended, single).
  303.  * @property ezcFeedTextElement $rating 
  304.  *            The {@link http://www.w3.org/PICS/ PICS} rating for the channel. Equivalents:
  305.  *            ATOM-none,
  306.  *            RSS1-none,
  307.  *            RSS2-rating (optional, not recommended, single).
  308.  * @property ezcFeedSkipDaysElement $skipDays 
  309.  *            A hint for aggregators telling them which days they can skip when
  310.  *            reading the feed. Equivalents:
  311.  *            ATOM-none,
  312.  *            RSS1-none,
  313.  *            RSS2-skipDays (optional, not recommended, single).
  314.  * @property ezcFeedSkipHoursElement $skipHours 
  315.  *            A hint for aggregators telling them which hours they can skip when
  316.  *            reading the feed. Equivalents:
  317.  *            ATOM-none,
  318.  *            RSS1-none,
  319.  *            RSS2-skipHours (optional, not recommended, single).
  320.  * @property ezcFeedTextInputElement $textInput 
  321.  *            Specifies a text input box that can be displayed with the feed. Equivalents:
  322.  *            ATOM-none,
  323.  *            RSS1-textinput (optional, not recommended, single),
  324.  *            RSS2-textInput (optional, not recommended, single).
  325.  * @property ezcFeedTextElement $title 
  326.  *            Human readable title for the feed. For example, it can be the same
  327.  *            as the website title. Equivalents:
  328.  *            ATOM-title (required, single),
  329.  *            RSS1-title (required, single),
  330.  *            RSS2-title (required, single).
  331.  * @property ezcFeedTextElement $ttl 
  332.  *            Number of minutes that indicates how long a channel can be cached
  333.  *            before refreshing from the source. Equivalents:
  334.  *            ATOM-none,
  335.  *            RSS1-none,
  336.  *            RSS2-ttl (optional, not recommended, single).
  337.  * @property ezcFeedDateElement $updated 
  338.  *            The last time the feed was updated. Equivalents:
  339.  *            ATOM-updated (required, single),
  340.  *            RSS1-none,
  341.  *            RSS2-lastBuildDate (optional, recommended, single).
  342.  * @property ezcFeedPersonElement $webMaster 
  343.  *            The email address of the webmaster responsible for the feed. Equivalents:
  344.  *            ATOM-none,
  345.  *            RSS1-none,
  346.  *            RSS2-webMaster (optional, not recommended, single).
  347.  *
  348.  * @todo parse() and parseContent() should(?) handle common broken XML files
  349.  *        (for example if the first line is not <?xml version="1.0"?>)
  350.  *
  351.  * @package Feed
  352.  * @version //autogentag//
  353.  * @mainclass
  354.  */
  355. class ezcFeed
  356. {
  357.     /**
  358.      * The version of the feed generator, to be included in the generated feeds.
  359.      */
  360.     const GENERATOR_VERSION '//autogentag//';
  361.  
  362.     /**
  363.      * The uri of the feed generator, to be included in the generated feeds.
  364.      */
  365.     const GENERATOR_URI 'http://ezcomponents.org/docs/tutorials/Feed';
  366.  
  367.     /**
  368.      * Holds a list of all supported feed types.
  369.      *
  370.      * @var array(string=>string) 
  371.      */
  372.     private static $supportedFeedTypes array();
  373.  
  374.     /**
  375.      * Holds a list of all supported modules.
  376.      *
  377.      * @var array(string=>string) 
  378.      */
  379.     private static $supportedModules array();
  380.  
  381.     /**
  382.      * Holds a list of all supported modules prefixes.
  383.      *
  384.      * @var array(string=>string) 
  385.      */
  386.     private static $supportedModulesPrefixes array();
  387.  
  388.     /**
  389.      * Holds the feed type (eg. 'rss1').
  390.      *
  391.      * @var string 
  392.      */
  393.     private $feedType;
  394.  
  395.     /**
  396.      * Holds the feed content type (eg. 'application/rss+xml').
  397.      *
  398.      * @var string 
  399.      */
  400.     private $contentType;
  401.  
  402.     /**
  403.      * Holds the feed elements (ezcFeedElement).
  404.      *
  405.      * @var array(string=>mixed) 
  406.      */
  407.     private $elements;
  408.  
  409.     /**
  410.      * Holds the modules used by this feed.
  411.      *
  412.      * @var array(ezcFeedModule) 
  413.      */
  414.     private $modules array();
  415.  
  416.     /**
  417.      * Creates a new feed object.
  418.      *
  419.      * The $type value is used when calling generate() without specifying a
  420.      * feed type to output.
  421.      *
  422.      * @throws ezcFeedUnsupportedTypeException
  423.      *          if the feed type $type is not supported
  424.      *
  425.      * @param string $type The type of feed to create
  426.      */
  427.     public function __construct$type null )
  428.     {
  429.         self::initSupportedTypes();
  430.  
  431.         if $type !== null )
  432.         {
  433.             $type strtolower$type );
  434.  
  435.             if !issetself::$supportedFeedTypes[$type) )
  436.             {
  437.                 throw new ezcFeedUnsupportedTypeException$type );
  438.             }
  439.  
  440.             $this->feedType $type;
  441.             $className self::$supportedFeedTypes[$type];
  442.             $this->contentType constant"{$className}::CONTENT_TYPE);
  443.         }
  444.  
  445.         // set default values
  446.         $version ezcFeed::GENERATOR_VERSION === '//auto' 'gentag//' 'dev' ezcFeed::GENERATOR_VERSION;
  447.  
  448.         $generator $this->add'generator' );
  449.         $generator->name 'eZ Components Feed';
  450.         $generator->version $version;
  451.         $generator->url ezcFeed::GENERATOR_URI;
  452.     }
  453.  
  454.     /**
  455.      * Sets the property $name to $value.
  456.      *
  457.      * @param string $name The property name
  458.      * @param mixed $value The property value
  459.      * @ignore
  460.      */
  461.     public function __set$name$value )
  462.     {
  463.         switch $name )
  464.         {
  465.             case 'author':
  466.             case 'contributor':
  467.             case 'webMaster':
  468.                 $element $this->add$name );
  469.                 $element->name $value;
  470.                 break;
  471.  
  472.             case 'title':
  473.             case 'description':
  474.             case 'docs':
  475.             case 'ttl':
  476.             case 'rating':
  477.             case 'language':
  478.             case 'copyright':
  479.                 $element $this->add$name );
  480.                 $element->text $value;
  481.                 break;
  482.  
  483.             case 'generator':
  484.                 $element $this->add$name );
  485.                 $element->name $value;
  486.                 break;
  487.  
  488.             case 'item':
  489.                 $element $this->add$name );
  490.                 break;
  491.  
  492.             case 'published':
  493.             case 'updated':
  494.                 $element $this->add$name );
  495.                 $element->date $value;
  496.                 break;
  497.  
  498.             case 'textInput':
  499.                 $element $this->add$name );
  500.                 break;
  501.  
  502.             case 'skipDays':
  503.                 $element $this->add$name );
  504.                 break;
  505.  
  506.             case 'skipHours':
  507.                 $element $this->add$name );
  508.                 break;
  509.  
  510.             case 'link':
  511.                 $element $this->add$name );
  512.                 $element->href $value;
  513.                 break;
  514.  
  515.             case 'generator':
  516.                 $element $this->add$name );
  517.                 $element->name $value;
  518.                 break;
  519.  
  520.             case 'image':
  521.             case 'icon':
  522.                 $element $this->add$name );
  523.                 $element->link $value;
  524.                 break;
  525.  
  526.             case 'id':
  527.                 $element $this->add$name );
  528.                 $element->id $value;
  529.                 break;
  530.  
  531.             default:
  532.                 $supportedModules ezcFeed::getSupportedModules();
  533.                 if isset$supportedModules[$name) )
  534.                 {
  535.                     $this->setModule$name$value );
  536.                     return;
  537.                 }
  538.         }
  539.     }
  540.  
  541.     /**
  542.      * Returns the value of property $name.
  543.      *
  544.      * @throws ezcBasePropertyNotFoundException
  545.      *          If the property $name does not exist.
  546.      *
  547.      * @param string $name The property name
  548.      * @return mixed 
  549.      * @ignore
  550.      */
  551.     public function __get$name )
  552.     {
  553.         switch $name )
  554.         {
  555.             case 'author':
  556.             case 'category':
  557.             case 'cloud':
  558.             case 'contributor':
  559.             case 'copyright':
  560.             case 'description':
  561.             case 'docs':
  562.             case 'generator':
  563.             case 'icon':
  564.             case 'id':
  565.             case 'image':
  566.             case 'item':
  567.             case 'language':
  568.             case 'link':
  569.             case 'published':
  570.             case 'rating':
  571.             case 'skipDays':
  572.             case 'skipHours':
  573.             case 'textInput':
  574.             case 'title':
  575.             case 'ttl':
  576.             case 'updated':
  577.             case 'webMaster':
  578.                 if isset$this->elements[$name) )
  579.                 {
  580.                     return $this->elements[$name];
  581.                 }
  582.                 break;
  583.  
  584.             default:
  585.                 $supportedModules ezcFeed::getSupportedModules();
  586.                 if isset$supportedModules[$name) )
  587.                 {
  588.                     if $this->hasModule$name ) )
  589.                     {
  590.                         return $this->getModule$name );
  591.                     }
  592.                     else
  593.                     {
  594.                         throw new ezcFeedUndefinedModuleException$name );
  595.                     }
  596.                 }
  597.  
  598.                 throw new ezcFeedUnsupportedModuleException$name );
  599.         }
  600.     }
  601.  
  602.     /**
  603.      * Returns if the property $name is set.
  604.      *
  605.      * @param string $name The property name
  606.      * @return bool 
  607.      * @ignore
  608.      */
  609.     public function __isset$name )
  610.     {
  611.         switch $name )
  612.         {
  613.             case 'author':
  614.             case 'category':
  615.             case 'cloud':
  616.             case 'contributor':
  617.             case 'copyright':
  618.             case 'description':
  619.             case 'docs':
  620.             case 'generator':
  621.             case 'icon':
  622.             case 'id':
  623.             case 'image':
  624.             case 'item':
  625.             case 'language':
  626.             case 'link':
  627.             case 'published':
  628.             case 'rating':
  629.             case 'skipDays':
  630.             case 'skipHours':
  631.             case 'textInput':
  632.             case 'title':
  633.             case 'ttl':
  634.             case 'updated':
  635.             case 'webMaster':
  636.                 return isset$this->elements[$name);
  637.  
  638.             default:
  639.                 $supportedModules ezcFeed::getSupportedModules();
  640.                 if isset$supportedModules[$name) )
  641.                 {
  642.                     return $this->hasModule$name );
  643.                 }
  644.         }
  645.  
  646.         return false;
  647.     }
  648.  
  649.     /**
  650.      * Adds a new module to this item and returns it.
  651.      *
  652.      * @param string $name The name of the module to add
  653.      * @return ezcFeedModule 
  654.      */
  655.     public function addModule$name )
  656.     {
  657.         $this->$name ezcFeedModule::create$name'feed' );
  658.         return $this->$name;
  659.     }
  660.  
  661.     /**
  662.      * Associates the module $module with the name $name.
  663.      *
  664.      * @param string $name The name of the module associate
  665.      * @param ezcFeedModule $module The module to set under the name $name
  666.      */
  667.     public function setModule$nameezcFeedModule $module )
  668.     {
  669.         $this->modules[$name$module;
  670.     }
  671.  
  672.     /**
  673.      * Returns the loaded module $name.
  674.      *
  675.      * @param string $name The name of the module to return
  676.      * @return ezcFeedModule 
  677.      */
  678.     public function getModule$name )
  679.     {
  680.         return $this->modules[$name];
  681.     }
  682.  
  683.     /**
  684.      * Returns true if the module $name is loaded, false otherwise.
  685.      *
  686.      * @param string $name The name of the module to check if loaded for this item
  687.      * @return bool 
  688.      */
  689.     public function hasModule$name )
  690.     {
  691.         return isset$this->modules[$name);
  692.     }
  693.  
  694.     /**
  695.      * Returns an array with all the modules loaded at feed-level.
  696.      *
  697.      * @return array(ezcFeedModule) 
  698.      */
  699.     public function getModules()
  700.     {
  701.         return $this->modules;
  702.     }
  703.  
  704.     /**
  705.      * Adds a new ezcFeedElement element with name $name and returns it.
  706.      *
  707.      * @throws ezcFeedUnsupportedElementException
  708.      *          if the element $name is not supported
  709.      *
  710.      * @param string $name The element name
  711.      * @return ezcFeedElement|null
  712.      */
  713.     public function add$name )
  714.     {
  715.         switch $name )
  716.         {
  717.             case 'item':
  718.                 $element new ezcFeedEntryElement();
  719.                 $this->elements[$name][$element;
  720.                 break;
  721.  
  722.             case 'author':
  723.             case 'contributor':
  724.             case 'webMaster':
  725.                 $element new ezcFeedPersonElement();
  726.                 $this->elements[$name][$element;
  727.                 break;
  728.  
  729.             case 'image':
  730.             case 'icon':
  731.                 $element new ezcFeedImageElement();
  732.                 $this->elements[$name$element;
  733.                 break;
  734.  
  735.             case 'category':
  736.                 $element new ezcFeedCategoryElement();
  737.                 $this->elements[$name][$element;
  738.                 break;
  739.  
  740.             case 'textInput':
  741.                 $element new ezcFeedTextInputElement();
  742.                 $this->elements[$name$element;
  743.                 break;
  744.  
  745.             case 'title':
  746.             case 'description':
  747.             case 'copyright':
  748.             case 'rating':
  749.             case 'comments':
  750.             case 'ttl':
  751.             case 'language':
  752.             case 'docs':
  753.                 $element new ezcFeedTextElement();
  754.                 $this->elements[$name$element;
  755.                 break;
  756.  
  757.             case 'skipDays':
  758.                 $element new ezcFeedSkipDaysElement();
  759.                 $this->elements[$name$element;
  760.                 break;
  761.  
  762.             case 'skipHours':
  763.                 $element new ezcFeedSkipHoursElement();
  764.                 $this->elements[$name$element;
  765.                 break;
  766.  
  767.             case 'link':
  768.                 $element new ezcFeedLinkElement();
  769.                 $this->elements[$name][$element;
  770.                 break;
  771.  
  772.             case 'generator':
  773.                 $element new ezcFeedGeneratorElement();
  774.                 $this->elements[$name$element;
  775.                 break;
  776.  
  777.             case 'cloud':
  778.                 $element new ezcFeedCloudElement();
  779.                 $this->elements[$name$element;
  780.                 break;
  781.  
  782.             case 'id':
  783.                 $element new ezcFeedIdElement();
  784.                 $this->elements[$name$element;
  785.                 break;
  786.  
  787.             case 'updated':
  788.             case 'published':
  789.                 $element new ezcFeedDateElement();
  790.                 $this->elements[$name$element;
  791.                 break;
  792.  
  793.             default:
  794.                 throw new ezcFeedUnsupportedElementException$name );
  795.         }
  796.  
  797.         return $element;
  798.     }
  799.  
  800.     /**
  801.      * Generates and returns an XML document of type $type from the current
  802.      * object.
  803.      *
  804.      * If the type was defined when creating the ezcFeed object, then that
  805.      * type will be used if no type is specified when calling generate().
  806.      *
  807.      * If no type was specified when calling the constructor and no type
  808.      * was specified when calling generate then an exception will be thrown.
  809.      *
  810.      * @throws ezcFeedUnsupportedTypeException
  811.      *          if the feed type $type is not supported
  812.      *
  813.      * @param string $type The feed type to generate
  814.      * @return string 
  815.      */
  816.     public function generate$type null )
  817.     {
  818.         if $this->feedType === null
  819.              && $type === null )
  820.         {
  821.             throw new ezcFeedUnsupportedTypeExceptionnull );
  822.         }
  823.  
  824.         if $type !== null )
  825.         {
  826.             $type strtolower$type );
  827.  
  828.             if !issetself::$supportedFeedTypes[$type) )
  829.             {
  830.                 throw new ezcFeedUnsupportedTypeException$type );
  831.             }
  832.         }
  833.  
  834.         if $type !== null )
  835.         {
  836.             $this->feedType $type;
  837.         }
  838.  
  839.         $className self::$supportedFeedTypes[$this->feedType];
  840.         $generator new $className$this );
  841.  
  842.         $this->contentType constant"{$className}::CONTENT_TYPE);
  843.         return $generator->generate();
  844.     }
  845.  
  846.     /**
  847.      * Parses the XML document in the $uri and returns an ezcFeed object with
  848.      * the type autodetected from the XML document.
  849.      *
  850.      * Example of parsing an XML document stored at an URL:
  851.      * <code>
  852.      * $feed = ezcFeed::parse( 'http://www.example.com/rss2.xml' );
  853.      * </code>
  854.      *
  855.      * Example of parsing an XML document protected with HTTP authentication:
  856.      * <code>
  857.      * $feed = ezcFeed::parse( 'http://username:password@www.example.com/rss2.xml' );
  858.      * </code>
  859.      *
  860.      * If trying to parse an XML document protected with HTTP authentication
  861.      * without providing a valid username and password, the exception
  862.      * {@link ezcFeedParseErrorException} will be thrown.
  863.      *
  864.      * Example of parsing an XML document stored in a local file:
  865.      * <code>
  866.      * $feed = ezcFeed::parse( '/tmp/feed.xml' );
  867.      * </code>
  868.      *
  869.      * @throws ezcBaseFileNotFoundException
  870.      *          If the XML file at $uri could not be found.
  871.      * @throws ezcFeedParseErrorException
  872.      *          If the content at $uri is not a valid XML document.
  873.      *
  874.      * @param string $uri An URI which stores an XML document
  875.      * @return ezcFeed 
  876.      */
  877.     public static function parse$uri )
  878.     {
  879.         if !file_exists$uri ) )
  880.         {
  881.             // hide the notices caused by getaddrinfo (php_network_getaddresses)
  882.             // in case of unreachable hosts ("Name or service not known")
  883.             $headers @get_headers$uri );
  884.             // HTTP headers
  885.             // 200 = OK
  886.             // 301 = moved permanently
  887.             // 302 = found
  888.             // 307 = temporary redirect
  889.             if preg_match"@200|301|302|307@"$headers[0=== )
  890.             {
  891.                 throw new ezcBaseFileNotFoundException$uri );
  892.             }
  893.         }
  894.  
  895.         $xml new DOMDocument();
  896.         $oldSetting libxml_use_internal_errorstrue );
  897.         $retval $xml->load$uri );
  898.         libxml_use_internal_errors$oldSetting );
  899.  
  900.         if $retval === false )
  901.         {
  902.             libxml_clear_errors();
  903.             throw new ezcFeedParseErrorException$uri"It is not a valid XML file" );
  904.         }
  905.  
  906.         return self::dispatchXml$xml );
  907.     }
  908.  
  909.     /**
  910.      * Parses the XML document stored in $content and returns an ezcFeed object
  911.      * with the type autodetected from the XML document.
  912.      *
  913.      * Example of parsing an XML document stored in a string:
  914.      * <code>
  915.      * // $xmlString contains a valid XML string
  916.      * $feed = ezcFeed::parseContent( $xmlString );
  917.      * </code>
  918.      *
  919.      * @throws ezcFeedParseErrorException
  920.      *          If $content is not a valid XML document.
  921.      *
  922.      * @param string $content A string variable which stores an XML document
  923.      * @return ezcFeed 
  924.      */
  925.     public static function parseContent$content )
  926.     {
  927.         if empty$content ) )
  928.         {
  929.             throw new ezcFeedParseErrorExceptionnull"Content is empty" );
  930.         }
  931.  
  932.         $xml new DOMDocument();
  933.         $oldSetting libxml_use_internal_errorstrue );
  934.         $retval $xml->loadXML$content );
  935.         libxml_use_internal_errors$oldSetting );
  936.  
  937.         if $retval === false )
  938.         {
  939.             libxml_clear_errors();
  940.             throw new ezcFeedParseErrorExceptionnull"Content is no valid XML" );
  941.         }
  942.  
  943.         return self::dispatchXml$xml );
  944.     }
  945.  
  946.     /**
  947.      * Returns the supported feed types.
  948.      *
  949.      * The array returned is (default):
  950.      * <code>
  951.      * array(
  952.      *    'rss1' => 'ezcFeedRss1',
  953.      *    'rss2' => 'ezcFeedRss2',
  954.      *    'atom' => 'ezcFeedAtom'
  955.      * );
  956.      * </code>
  957.      *
  958.      * If the function {@link registerFeed} was used to add another supported feed
  959.      * type to ezcFeed, it will show up in the returned array as well.
  960.      *
  961.      * @return array(string) 
  962.      */
  963.     public static function getSupportedTypes()
  964.     {
  965.         return self::$supportedFeedTypes;
  966.     }
  967.  
  968.     /**
  969.      * Returns the supported feed modules.
  970.      *
  971.      * The array returned is (default):
  972.      * <code>
  973.      * array(
  974.      *    'Content'         => 'ezcFeedContentModule',
  975.      *    'CreativeCommons' => 'ezcFeedCreativeCommonsModule',
  976.      *    'DublinCore'      => 'ezcFeedDublinCoreModule',
  977.      *    'Geo'             => 'ezcFeedGeoModule',
  978.      *    'GeoRss'          => 'ezcFeedGeoRssModule',
  979.      *    'iTunes'          => 'ezcFeedITunesModule'
  980.      * );
  981.      * </code>
  982.      *
  983.      * If the function {@link registerModule} was used to add another supported
  984.      * module type to ezcFeed, it will show up in the returned array as well.
  985.      *
  986.      * @return array(string=>string) 
  987.      */
  988.     public static function getSupportedModules()
  989.     {
  990.         return self::$supportedModules;
  991.     }
  992.  
  993.     /**
  994.      * Returns the supported feed modules prefixes.
  995.      *
  996.      * The array returned is (default):
  997.      * <code>
  998.      * array(
  999.      *    'content'         => 'Content',
  1000.      *    'creativeCommons' => 'CreativeCommons',
  1001.      *    'dc'              => 'DublinCore',
  1002.      *    'geo'             => 'Geo',
  1003.      *    'georss'          => 'GeoRss',
  1004.      *    'itunes'          => 'iTunes'
  1005.      * );
  1006.      * </code>
  1007.      *
  1008.      * If the function {@link registerModule} was used to add another supported
  1009.      * module type to ezcFeed, it will show up in the returned array as well.
  1010.      *
  1011.      * @return array(string=>string) 
  1012.      */
  1013.     public static function getSupportedModulesPrefixes()
  1014.     {
  1015.         return self::$supportedModulesPrefixes;
  1016.     }
  1017.  
  1018.     /**
  1019.      * Returns the feed type of this feed object (eg. 'rss2').
  1020.      *
  1021.      * @return string 
  1022.      */
  1023.     public function getFeedType()
  1024.     {
  1025.         return $this->feedType;
  1026.     }
  1027.  
  1028.     /**
  1029.      * Returns the feed content type of this feed object
  1030.      * (eg. 'application/rss+xml').
  1031.      *
  1032.      * @return string 
  1033.      */
  1034.     public function getContentType()
  1035.     {
  1036.         return $this->contentType;
  1037.     }
  1038.  
  1039.     /**
  1040.      * Adds the feed type $name to the supported list of feed types.
  1041.      *
  1042.      * After registering a feed type, it can be used to create or parse feed
  1043.      * documents.
  1044.      *
  1045.      * Example of creating a feed with a user-defined type:
  1046.      * <code>
  1047.      * ezcFeed::registerFeed( 'opml', 'myOpmlHandler');
  1048.      *
  1049.      * $feed = new ezcFeed( 'opml' );
  1050.      * // add properties for the Opml feed type to $feed
  1051.      * </code>
  1052.      *
  1053.      * In the above example, myOpmlHandler extends {@link ezcFeedProcessor}
  1054.      * and implements {@link ezcFeedParser}.
  1055.      *
  1056.      * @param string $name The feed type (eg. 'opml' )
  1057.      * @param string $class The handler class for this feed type (eg. 'myOpmlHandler')
  1058.      */
  1059.     public static function registerFeed$name$class )
  1060.     {
  1061.         self::$supportedFeedTypes[$name$class;
  1062.     }
  1063.  
  1064.     /**
  1065.      * Removes a previously registered feed type from the list of supported
  1066.      * feed types.
  1067.      *
  1068.      * @param string $name The name of the feed type to remove (eg. 'opml')
  1069.      */
  1070.     public static function unregisterFeed$name )
  1071.     {
  1072.         if issetself::$supportedFeedTypes[$name) )
  1073.         {
  1074.             unsetself::$supportedFeedTypes[$name);
  1075.         }
  1076.     }
  1077.  
  1078.     /**
  1079.      * Adds the module $name to the supported list of modules.
  1080.      *
  1081.      * After registering a module, it can be used to create or parse feed
  1082.      * documents.
  1083.      *
  1084.      * Example of creating a feed with a user-defined module:
  1085.      * <code>
  1086.      * ezcFeed::registerModule( 'Slash', 'mySlashHandler', 'slash');
  1087.      *
  1088.      * $feed = new ezcFeed( 'rss2' );
  1089.      * $item = $feed->add( 'item' );
  1090.      * $slash = $item->addModule( 'Slash' );
  1091.      * // add properties for the Slash module to $slash
  1092.      * </code>
  1093.      *
  1094.      * @param string $name The module name (eg. 'Slash' )
  1095.      * @param string $class The handler class for this module (eg. 'mySlashHandler')
  1096.      * @param string $namespacePrefix The XML namespace prefix for this module (eg. 'slash')
  1097.      */
  1098.     public static function registerModule$name$class$namespacePrefix )
  1099.     {
  1100.         self::$supportedModules[$name$class;
  1101.         self::$supportedModulesPrefixes[$namespacePrefix$name;
  1102.     }
  1103.  
  1104.     /**
  1105.      * Removes a previously registered module from the list of supported modules.
  1106.      *
  1107.      * @param string $name The name of the module to remove (eg. 'Slash')
  1108.      */
  1109.     public static function unregisterModule$name )
  1110.     {
  1111.         if issetself::$supportedModules[$name) )
  1112.         {
  1113.             $namePrefix null;
  1114.             foreach self::$supportedModulesPrefixes as $prefix => $module )
  1115.             {
  1116.                 if $module === $name )
  1117.                 {
  1118.                     $namePrefix $prefix;
  1119.                     break;
  1120.                 }
  1121.             }
  1122.             unsetself::$supportedModulesPrefixes[$prefix);
  1123.             unsetself::$supportedModules[$name);
  1124.         }
  1125.     }
  1126.  
  1127.     /**
  1128.      * Parses the $xml object by dispatching it to the processor that can
  1129.      * handle it.
  1130.      *
  1131.      * @throws ezcFeedParseErrorException
  1132.      *          If the $xml object could not be parsed by any available processor.
  1133.      *
  1134.      * @param DOMDocument $xml The XML object to parse
  1135.      * @return ezcFeed 
  1136.      */
  1137.     private static function dispatchXmlDOMDocument $xml )
  1138.     {
  1139.         if countself::getSupportedTypes() ) === )
  1140.         {
  1141.             self::initSupportedTypes();
  1142.         }
  1143.  
  1144.         foreach self::getSupportedTypes(as $feedType => $feedClass )
  1145.         {
  1146.             $canParse call_user_funcarray$feedClass'canParse' )$xml );
  1147.             if $canParse === true )
  1148.             {
  1149.                 $feed new ezcFeed$feedType );
  1150.                 $parser new $feedClass$feed );
  1151.                 return $parser->parse$xml );
  1152.             }
  1153.         }
  1154.  
  1155.         throw new ezcFeedParseErrorException$xml->documentURI'Feed type not recognized' );
  1156.     }
  1157.  
  1158.     /**
  1159.      * Initializes the supported feed types and modules to the default values.
  1160.      */
  1161.     private static function initSupportedTypes()
  1162.     {
  1163.         self::registerFeed'rss1''ezcFeedRss1' );
  1164.         self::registerFeed'rss2''ezcFeedRss2' );
  1165.         self::registerFeed'atom''ezcFeedAtom' );
  1166.  
  1167.         self::registerModule'Content''ezcFeedContentModule''content' );
  1168.         self::registerModule'CreativeCommons''ezcFeedCreativeCommonsModule''creativeCommons' );
  1169.         self::registerModule'DublinCore''ezcFeedDublinCoreModule''dc' );
  1170.         self::registerModule'Geo''ezcFeedGeoModule''geo' );
  1171.         self::registerModule'GeoRss''ezcFeedGeoRssModule''georss' );
  1172.         self::registerModule'iTunes''ezcFeedITunesModule''itunes' );
  1173.     }
  1174. }
  1175. ?>
Documentation generated by phpDocumentor 1.4.3