<?xml version="1.0" encoding="UTF-8"?>
<!-- Reviewed: no -->
<sect1 id="zend.feed.importing">
    <title>Importing Feeds</title>

    <para>
        <classname>Zend_Feed</classname> enables developers to retrieve feeds very easily. If you
        know the <acronym>URI</acronym> of a feed, simply use the
        <methodname>Zend_Feed::import()</methodname> method:
    </para>

    <programlisting language="php"><![CDATA[
$feed = Zend_Feed::import('http://feeds.example.com/feedName');
]]></programlisting>

    <para>
        You can also use <classname>Zend_Feed</classname> to fetch the contents of a feed from a
        file or the contents of a <acronym>PHP</acronym> string variable:
    </para>

    <programlisting language="php"><![CDATA[
// importing a feed from a text file
$feedFromFile = Zend_Feed::importFile('feed.xml');

// importing a feed from a PHP string variable
$feedFromPHP = Zend_Feed::importString($feedString);
]]></programlisting>

    <para>
        In each of the examples above, an object of a class that extends
        <classname>Zend_Feed_Abstract</classname> is returned upon success, depending on the type of
        the feed. If an <acronym>RSS</acronym> feed were retrieved via one of the import methods
        above, then a <classname>Zend_Feed_Rss</classname> object would be returned. On the other
        hand, if an Atom feed were imported, then a <classname>Zend_Feed_Atom</classname> object is
        returned. The import methods will also throw a <classname>Zend_Feed_Exception</classname>
        object upon failure, such as an unreadable or malformed feed.
    </para>

    <sect2 id="zend.feed.importing.custom">
        <title>Custom feeds</title>

        <para>
            <classname>Zend_Feed</classname> enables developers to create custom feeds very easily.
            You just have to create an array and to import it with <classname>Zend_Feed</classname>.
            This array can be imported with <methodname>Zend_Feed::importArray()</methodname> or
            with <methodname>Zend_Feed::importBuilder()</methodname>. In this last case the array
            will be computed on the fly by a custom data source implementing
            <classname>Zend_Feed_Builder_Interface</classname>.
        </para>

        <sect3 id="zend.feed.importing.custom.importarray">
            <title>Importing a custom array</title>

            <programlisting language="php"><![CDATA[
// importing a feed from an array
$atomFeedFromArray = Zend_Feed::importArray($array);

// the following line is equivalent to the above;
// by default a Zend_Feed_Atom instance is returned
$atomFeedFromArray = Zend_Feed::importArray($array, 'atom');

// importing a rss feed from an array
$rssFeedFromArray = Zend_Feed::importArray($array, 'rss');
]]></programlisting>

            <para>
                The format of the array must conform to this structure:
            </para>

            <programlisting language="php"><![CDATA[
array(
    //required
    'title' => 'title of the feed',
    'link'  => 'canonical url to the feed',

    // optional
    'lastUpdate' => 'timestamp of the update date',
    'published'  => 'timestamp of the publication date',

    // required
    'charset' => 'charset of the textual data',

    // optional
    'description' => 'short description of the feed',
    'author'      => 'author/publisher of the feed',
    'email'       => 'email of the author',

    // optional, ignored if atom is used
    'webmaster' => 'email address for person responsible '
                .  'for technical issues',

    // optional
    'copyright' => 'copyright notice',
    'image'     => 'url to image',
    'generator' => 'generator',
    'language'  => 'language the feed is written in',

    // optional, ignored if atom is used
    'ttl'    => 'how long in minutes a feed can be cached '
             .  'before refreshing',
    'rating' => 'The PICS rating for the channel.',

    // optional, ignored if atom is used
    // a cloud to be notified of updates
    'cloud'       => array(
        // required
        'domain' => 'domain of the cloud, e.g. rpc.sys.com',

        // optional, defaults to 80
        'port' => 'port to connect to',

        // required
        'path'              => 'path of the cloud, e.g. /RPC2',
        'registerProcedure' => 'procedure to call, e.g. myCloud.rssPlsNotify',
        'protocol'          => 'protocol to use, e.g. soap or xml-rpc'
    ),

    // optional, ignored if atom is used
    // a text input box that can be displayed with the feed
    'textInput'   => array(
        // required
        'title'       => 'label of the Submit button in the text input area',
        'description' => 'explains the text input area',
        'name'        => 'the name of the text object in the text input area',
        'link'        => 'URL of the CGI script processing text input requests'
    ),

    // optional, ignored if atom is used
    // Hint telling aggregators which hours they can skip
    'skipHours' => array(
        // up to 24 rows whose value is a number between 0 and 23
        // e.g 13 (1pm)
        'hour in 24 format'
    ),

    // optional, ignored if atom is used
    // Hint telling aggregators which days they can skip
    'skipDays ' => array(
        // up to 7 rows whose value is
        // Monday, Tuesday, Wednesday, Thursday, Friday, Saturday or Sunday
        // e.g Monday
        'a day to skip'
    ),

    // optional, ignored if atom is used
    // Itunes extension data
    'itunes' => array(
        // optional, default to the main author value
        'author' => 'Artist column',

        // optional, default to the main author value
        // Owner of the podcast
        'owner' => array(
            'name'  => 'name of the owner',
            'email' => 'email of the owner'
        ),

        // optional, default to the main image value
        'image' => 'album/podcast art',

        // optional, default to the main description value
        'subtitle' => 'short description',
        'summary'  => 'longer description',

        // optional
        'block' => 'Prevent an episode from appearing (yes|no)',

        // required, Category column and in iTunes Music Store Browse
        'category' => array(
            // up to 3 rows
            array(
                // required
                'main' => 'main category',

                // optional
                'sub'  => 'sub category'
            )
        ),

        // optional
        'explicit'     => 'parental advisory graphic (yes|no|clean)',
        'keywords'     => 'a comma separated list of 12 keywords maximum',
        'new-feed-url' => 'used to inform iTunes of new feed URL location'
    ),

    'entries' => array(
        array(
            //required
            'title' => 'title of the feed entry',
            'link'  => 'url to a feed entry',

            // required, only text, no html
            'description' => 'short version of a feed entry',

            // optional
            'guid' => 'id of the article, '
                   .  'if not given link value will used',

            // optional, can contain html
            'content' => 'long version',

            // optional
            'lastUpdate' => 'timestamp of the publication date',
            'comments'   => 'comments page of the feed entry',
            'commentRss' => 'the feed url of the associated comments',

            // optional, original source of the feed entry
            'source' => array(
                // required
                'title' => 'title of the original source',
                'url'   => 'url of the original source'
            ),

            // optional, list of the attached categories
            'category' => array(
                array(
                    // required
                    'term' => 'first category label',

                    // optional
                    'scheme' => 'url that identifies a categorization scheme'
                ),

                array(
                    // data for the second category and so on
                )
            ),

            // optional, list of the enclosures of the feed entry
            'enclosure'    => array(
                array(
                    // required
                    'url' => 'url of the linked enclosure',

                    // optional
                    'type' => 'mime type of the enclosure',
                    'length' => 'length of the linked content in octets'
                ),

                array(
                    //data for the second enclosure and so on
                )
            )
        ),

        array(
            //data for the second entry and so on
        )
    )
);
]]></programlisting>

            <para>
                References:
            </para>

            <itemizedlist>
                <listitem>
                    <para>
                        <acronym>RSS</acronym> 2.0 specification: <ulink
                            url="http://blogs.law.harvard.edu/tech/rss">RSS 2.0</ulink>
                    </para>
                </listitem>

                <listitem>
                    <para>
                        Atom specification: <ulink
                            url="http://tools.ietf.org/html/rfc4287">RFC 4287</ulink>
                    </para>
                </listitem>

                <listitem>
                    <para>
                        <acronym>WFW</acronym> specification: <ulink
                            url="http://wellformedweb.org/news/wfw_namespace_elements">Well
                            Formed Web</ulink>
                    </para>
                </listitem>

                <listitem>
                    <para>
                        iTunes specification: <ulink
                            url="http://www.apple.com/itunes/store/podcaststechspecs.html">iTunes
                            Technical Specifications</ulink>
                    </para>
                </listitem>
            </itemizedlist>
        </sect3>

        <sect3 id="zend.feed.importing.custom.importbuilder">
            <title>Importing a custom data source</title>

            <para>
                You can create a <classname>Zeed_Feed</classname> instance from any data source
                implementing <classname>Zend_Feed_Builder_Interface</classname>. You just have to
                implement the <methodname>getHeader()</methodname> and
                <methodname>getEntries()</methodname> methods to be able to use your object with
                <methodname>Zend_Feed::importBuilder()</methodname>. As a simple reference
                implementation, you can use <classname>Zend_Feed_Builder</classname>, which takes
                an array in its constructor, performs some minor validation, and then can be used
                in the <methodname>importBuilder()</methodname> method. The
                <methodname>getHeader()</methodname> method must return an instance of
                <classname>Zend_Feed_Builder_Header</classname>, and
                <methodname>getEntries()</methodname> must return an array of
                <classname>Zend_Feed_Builder_Entry</classname> instances.
            </para>

            <note>
                <para>
                    <classname>Zend_Feed_Builder</classname> serves as a concrete implementation to
                    demonstrate the usage. Users are encouraged to make their own classes to
                    implement <classname>Zend_Feed_Builder_Interface</classname>.
                </para>
            </note>

            <para>
                Here is an example of <methodname>Zend_Feed::importBuilder()</methodname> usage:
            </para>

            <programlisting language="php"><![CDATA[
// importing a feed from a custom builder source
$atomFeedFromArray =
    Zend_Feed::importBuilder(new Zend_Feed_Builder($array));

// the following line is equivalent to the above;
// by default a Zend_Feed_Atom instance is returned
$atomFeedFromArray =
    Zend_Feed::importBuilder(new Zend_Feed_Builder($array), 'atom');

// importing a rss feed from a custom builder array
$rssFeedFromArray =
    Zend_Feed::importBuilder(new Zend_Feed_Builder($array), 'rss');
]]></programlisting>
        </sect3>

        <sect3 id="zend.feed.importing.custom.dump">
            <title>Dumping the contents of a feed</title>

            <para>
                To dump the contents of a <classname>Zend_Feed_Abstract</classname> instance, you
                may use <methodname>send()</methodname> or <methodname>saveXml()</methodname>
                methods.
            </para>

            <programlisting language="php"><![CDATA[
assert($feed instanceof Zend_Feed_Abstract);

// dump the feed to standard output
print $feed->saveXML();

// send http headers and dump the feed
$feed->send();
]]></programlisting>
        </sect3>
    </sect2>
</sect1>
<!--
vim:se ts=4 sw=4 et:
-->
