Skip to content
Snippets Groups Projects
feedcreator.class.php 57.4 KiB
Newer Older
andi's avatar
andi committed


/**
 * RSSCreator20 is a FeedCreator that implements RDF Site Summary (RSS) 2.0.
 *
 * @see http://backend.userland.com/rss
 * @since 1.3
 * @author Kai Blankenhorn <kaib@bitfolge.de>
 */
class RSSCreator20 extends RSSCreator091 {

    function RSSCreator20() {
        parent::_setRSSVersion("2.0");
    }
Andreas Gohr's avatar
Andreas Gohr committed

andi's avatar
andi committed
}


/**
 * PIECreator01 is a FeedCreator that implements the emerging PIE specification,
 * as in http://intertwingly.net/wiki/pie/Syntax.
 *
 * @deprecated
 * @since 1.3
 * @author Scott Reynen <scott@randomchaos.com> and Kai Blankenhorn <kaib@bitfolge.de>
 */
class PIECreator01 extends FeedCreator {
Andreas Gohr's avatar
Andreas Gohr committed

    function PIECreator01() {
        $this->encoding = "utf-8";
    }

    function createFeed() {
        $feed = "<?xml version=\"1.0\" encoding=\"".$this->encoding."\"?>\n";
        $feed.= $this->_createStylesheetReferences();
        $feed.= "<feed version=\"0.1\" xmlns=\"http://example.com/newformat#\">\n";
        $feed.= "    <title>".FeedCreator::iTrunc(htmlspecialchars($this->title),100)."</title>\n";
        $this->truncSize = 500;
        $feed.= "    <subtitle>".$this->getDescription()."</subtitle>\n";
        $feed.= "    <link>".$this->link."</link>\n";
        for ($i=0;$i<count($this->items);$i++) {
            $feed.= "    <entry>\n";
            $feed.= "        <title>".FeedCreator::iTrunc(htmlspecialchars(strip_tags($this->items[$i]->title)),100)."</title>\n";
            $feed.= "        <link>".htmlspecialchars($this->items[$i]->link)."</link>\n";
            $itemDate = new FeedDate($this->items[$i]->date);
            $feed.= "        <created>".htmlspecialchars($itemDate->iso8601())."</created>\n";
            $feed.= "        <issued>".htmlspecialchars($itemDate->iso8601())."</issued>\n";
            $feed.= "        <modified>".htmlspecialchars($itemDate->iso8601())."</modified>\n";
            $feed.= "        <id>".htmlspecialchars($this->items[$i]->guid)."</id>\n";
            if ($this->items[$i]->author!="") {
                $feed.= "        <author>\n";
                $feed.= "            <name>".htmlspecialchars($this->items[$i]->author)."</name>\n";
                if ($this->items[$i]->authorEmail!="") {
                    $feed.= "            <email>".$this->items[$i]->authorEmail."</email>\n";
                }
                $feed.="        </author>\n";
            }
            $feed.= "        <content type=\"text/html\" xml:lang=\"en-us\">\n";
            $feed.= "            <div xmlns=\"http://www.w3.org/1999/xhtml\">".$this->items[$i]->getDescription()."</div>\n";
            $feed.= "        </content>\n";
            $feed.= "    </entry>\n";
Andreas Gohr's avatar
Andreas Gohr committed
        }
        $feed.= "</feed>\n";
        return $feed;
Andreas Gohr's avatar
Andreas Gohr committed
    }
}

/**
 * AtomCreator10 is a FeedCreator that implements the atom specification,
 * as in http://www.atomenabled.org/developers/syndication/atom-format-spec.php
 * Please note that just by using AtomCreator10 you won't automatically
 * produce valid atom files. For example, you have to specify either an editor
 * for the feed or an author for every single feed item.
 *
 * Some elements have not been implemented yet. These are (incomplete list):
 * author URL, item author's email and URL, item contents, alternate links,
 * other link content types than text/html. Some of them may be created with
 * AtomCreator10::additionalElements.
 *
 * @see FeedCreator#additionalElements
 * @since 1.7.2-mod (modified)
 * @author Mohammad Hafiz Ismail (mypapit@gmail.com)
 */
 class AtomCreator10 extends FeedCreator {

    function AtomCreator10() {
        $this->contentType = "application/atom+xml";
        $this->encoding = "utf-8";
    }

    function createFeed() {
        $feed = "<?xml version=\"1.0\" encoding=\"".$this->encoding."\"?>\n";
        $feed.= $this->_createGeneratorComment();
        $feed.= $this->_createStylesheetReferences();
        $feed.= "<feed xmlns=\"http://www.w3.org/2005/Atom\"";
        if ($this->language!="") {
            $feed.= " xml:lang=\"".$this->language."\"";
        }
        $feed.= ">\n";
        $feed.= "    <title>".htmlspecialchars($this->title)."</title>\n";
        $feed.= "    <subtitle>".htmlspecialchars($this->description)."</subtitle>\n";
        $feed.= "    <link rel=\"alternate\" type=\"text/html\" href=\"".htmlspecialchars($this->link)."\"/>\n";
        $feed.= "    <id>".htmlspecialchars($this->link)."</id>\n";
        $now = new FeedDate();
        $feed.= "    <updated>".htmlspecialchars($now->iso8601())."</updated>\n";
        if ($this->editor!="") {
            $feed.= "    <author>\n";
            $feed.= "        <name>".$this->editor."</name>\n";
            if ($this->editorEmail!="") {
                $feed.= "        <email>".$this->editorEmail."</email>\n";
            }
            $feed.= "    </author>\n";
        }
        $feed.= "    <generator>".FEEDCREATOR_VERSION."</generator>\n";
        $feed.= "<link rel=\"self\" type=\"application/atom+xml\" href=\"". $this->syndicationURL . "\" />\n";
        $feed.= $this->_createAdditionalElements($this->additionalElements, "    ");
        for ($i=0;$i<count($this->items);$i++) {
            $feed.= "    <entry>\n";
            $feed.= "        <title>".htmlspecialchars(strip_tags($this->items[$i]->title))."</title>\n";
            $feed.= "        <link rel=\"alternate\" type=\"text/html\" href=\"".htmlspecialchars($this->items[$i]->link)."\"/>\n";
            if ($this->items[$i]->date=="") {
                $this->items[$i]->date = time();
            }
            $itemDate = new FeedDate($this->items[$i]->date);
            $feed.= "        <published>".htmlspecialchars($itemDate->iso8601())."</published>\n";
            $feed.= "        <updated>".htmlspecialchars($itemDate->iso8601())."</updated>\n";
            $feed.= "        <id>".htmlspecialchars($this->items[$i]->link)."</id>\n";
            $feed.= $this->_createAdditionalElements($this->items[$i]->additionalElements, "        ");
            if ($this->items[$i]->author!="") {
                $feed.= "        <author>\n";
                $feed.= "            <name>".htmlspecialchars($this->items[$i]->author)."</name>\n";
                $feed.= "        </author>\n";
            }
            if ($this->items[$i]->description!="") {
                $feed.= "        <summary>".htmlspecialchars($this->items[$i]->description)."</summary>\n";
            }
            if ($this->items[$i]->enclosure != NULL) {
            $feed.="        <link rel=\"enclosure\" href=\"". $this->items[$i]->enclosure->url ."\" type=\"". $this->items[$i]->enclosure->type."\"  length=\"". $this->items[$i]->enclosure->length . "\" />\n";
            }
            $feed.= "    </entry>\n";
        }
        $feed.= "</feed>\n";
        return $feed;
    }


andi's avatar
andi committed
}


/**
 * AtomCreator03 is a FeedCreator that implements the atom specification,
 * as in http://www.intertwingly.net/wiki/pie/FrontPage.
 * Please note that just by using AtomCreator03 you won't automatically
 * produce valid atom files. For example, you have to specify either an editor
 * for the feed or an author for every single feed item.
 *
 * Some elements have not been implemented yet. These are (incomplete list):
Andreas Gohr's avatar
Andreas Gohr committed
 * author URL, item author's email and URL, item contents, alternate links,
andi's avatar
andi committed
 * other link content types than text/html. Some of them may be created with
 * AtomCreator03::additionalElements.
 *
 * @see FeedCreator#additionalElements
 * @since 1.6
 * @author Kai Blankenhorn <kaib@bitfolge.de>, Scott Reynen <scott@randomchaos.com>
 */
class AtomCreator03 extends FeedCreator {

    function AtomCreator03() {
        $this->contentType = "application/atom+xml";
        $this->encoding = "utf-8";
Andreas Gohr's avatar
Andreas Gohr committed
    }

    function createFeed() {
        $feed = "<?xml version=\"1.0\" encoding=\"".$this->encoding."\"?>\n";
        $feed.= $this->_createGeneratorComment();
        $feed.= $this->_createStylesheetReferences();
        $feed.= "<feed version=\"0.3\" xmlns=\"http://purl.org/atom/ns#\"";
        if ($this->language!="") {
            $feed.= " xml:lang=\"".$this->language."\"";
Andreas Gohr's avatar
Andreas Gohr committed
        }
        $feed.= ">\n";
        $feed.= "    <title>".htmlspecialchars($this->title)."</title>\n";
        $feed.= "    <tagline>".htmlspecialchars($this->description)."</tagline>\n";
        $feed.= "    <link rel=\"alternate\" type=\"text/html\" href=\"".htmlspecialchars($this->link)."\"/>\n";
        $feed.= "    <id>".htmlspecialchars($this->link)."</id>\n";
        $now = new FeedDate();
        $feed.= "    <modified>".htmlspecialchars($now->iso8601())."</modified>\n";
        if ($this->editor!="") {
            $feed.= "    <author>\n";
            $feed.= "        <name>".$this->editor."</name>\n";
            if ($this->editorEmail!="") {
                $feed.= "        <email>".$this->editorEmail."</email>\n";
            }
            $feed.= "    </author>\n";
        }
        $feed.= "    <generator>".FEEDCREATOR_VERSION."</generator>\n";
        $feed.= $this->_createAdditionalElements($this->additionalElements, "    ");
        for ($i=0;$i<count($this->items);$i++) {
            $feed.= "    <entry>\n";
            $feed.= "        <title>".htmlspecialchars(strip_tags($this->items[$i]->title))."</title>\n";
            $feed.= "        <link rel=\"alternate\" type=\"text/html\" href=\"".htmlspecialchars($this->items[$i]->link)."\"/>\n";
            if ($this->items[$i]->date=="") {
                $this->items[$i]->date = time();
            }
            $itemDate = new FeedDate($this->items[$i]->date);
            $feed.= "        <created>".htmlspecialchars($itemDate->iso8601())."</created>\n";
            $feed.= "        <issued>".htmlspecialchars($itemDate->iso8601())."</issued>\n";
            $feed.= "        <modified>".htmlspecialchars($itemDate->iso8601())."</modified>\n";
            $feed.= "        <id>".htmlspecialchars($this->items[$i]->link)."</id>\n";
            $feed.= $this->_createAdditionalElements($this->items[$i]->additionalElements, "        ");
            if ($this->items[$i]->author!="") {
                $feed.= "        <author>\n";
                $feed.= "            <name>".htmlspecialchars($this->items[$i]->author)."</name>\n";
                $feed.= "        </author>\n";
            }
            if ($this->items[$i]->description!="") {
                $feed.= "        <summary>".htmlspecialchars($this->items[$i]->description)."</summary>\n";
            }
            $feed.= "    </entry>\n";
        }
        $feed.= "</feed>\n";
        return $feed;
Andreas Gohr's avatar
Andreas Gohr committed
    }
andi's avatar
andi committed
}


/**
 * MBOXCreator is a FeedCreator that implements the mbox format
 * as described in http://www.qmail.org/man/man5/mbox.html
 *
 * @since 1.3
 * @author Kai Blankenhorn <kaib@bitfolge.de>
 */
class MBOXCreator extends FeedCreator {

    function MBOXCreator() {
        $this->contentType = "text/plain";
        $this->encoding = "utf-8";
    }

    function qp_enc($input = "", $line_max = 76) {
        $hex = array('0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F');
        $lines = preg_split("/(?:\r\n|\r|\n)/", $input);
        $eol = "\r\n";
        $escape = "=";
        $output = "";
        while( list(, $line) = each($lines) ) {
            //$line = rtrim($line); // remove trailing white space -> no =20\r\n necessary
            $linlen = strlen($line);
            $newline = "";
            for($i = 0; $i < $linlen; $i++) {
                $c = substr($line, $i, 1);
                $dec = ord($c);
                if ( ($dec == 32) && ($i == ($linlen - 1)) ) { // convert space at eol only
                    $c = "=20";
                } elseif ( ($dec == 61) || ($dec < 32 ) || ($dec > 126) ) { // always encode "\t", which is *not* required
                    $h2 = floor($dec/16); $h1 = floor($dec%16);
                    $c = $escape.$hex["$h2"].$hex["$h1"];
                }
                if ( (strlen($newline) + strlen($c)) >= $line_max ) { // CRLF is not counted
                    $output .= $newline.$escape.$eol; // soft line break; " =\r\n" is okay
                    $newline = "";
                }
                $newline .= $c;
            } // end of for
            $output .= $newline.$eol;
Andreas Gohr's avatar
Andreas Gohr committed
        }
        return trim($output);
    }


    /**
     * Builds the MBOX contents.
     * @return    string    the feed's complete text
     */
    function createFeed() {
        for ($i=0;$i<count($this->items);$i++) {
            if ($this->items[$i]->author!="") {
                $from = $this->items[$i]->author;
            } else {
                $from = $this->title;
            }
            $itemDate = new FeedDate($this->items[$i]->date);
            $feed.= "From ".strtr(MBOXCreator::qp_enc($from)," ","_")." ".date("D M d H:i:s Y",$itemDate->unix())."\n";
            $feed.= "Content-Type: text/plain;\n";
            $feed.= "   charset=\"".$this->encoding."\"\n";
            $feed.= "Content-Transfer-Encoding: quoted-printable\n";
            $feed.= "Content-Type: text/plain\n";
            $feed.= "From: \"".MBOXCreator::qp_enc($from)."\"\n";
            $feed.= "Date: ".$itemDate->rfc822()."\n";
            $feed.= "Subject: ".MBOXCreator::qp_enc(FeedCreator::iTrunc($this->items[$i]->title,100))."\n";
            $feed.= "\n";
            $body = chunk_split(MBOXCreator::qp_enc($this->items[$i]->description));
            $feed.= preg_replace("~\nFrom ([^\n]*)(\n?)~","\n>From $1$2\n",$body);
            $feed.= "\n";
            $feed.= "\n";
Andreas Gohr's avatar
Andreas Gohr committed
        }
        return $feed;
Andreas Gohr's avatar
Andreas Gohr committed
    }

    /**
     * Generate a filename for the feed cache file. Overridden from FeedCreator to prevent XML data types.
     * @return string the feed cache filename
     * @since 1.4
     * @access private
     */
    function _generateFilename() {
        $fileInfo = pathinfo($_SERVER["PHP_SELF"]);
        return substr($fileInfo["basename"],0,-(strlen($fileInfo["extension"])+1)).".mbox";
Andreas Gohr's avatar
Andreas Gohr committed
    }
andi's avatar
andi committed
}


/**
 * OPMLCreator is a FeedCreator that implements OPML 1.0.
Andreas Gohr's avatar
Andreas Gohr committed
 *
andi's avatar
andi committed
 * @see http://opml.scripting.com/spec
 * @author Dirk Clemens, Kai Blankenhorn
 * @since 1.5
 */
class OPMLCreator extends FeedCreator {

    function OPMLCreator() {
        $this->encoding = "utf-8";
Andreas Gohr's avatar
Andreas Gohr committed
    }

    function createFeed() {
        $feed = "<?xml version=\"1.0\" encoding=\"".$this->encoding."\"?>\n";
        $feed.= $this->_createGeneratorComment();
        $feed.= $this->_createStylesheetReferences();
        $feed.= "<opml xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\">\n";
        $feed.= "    <head>\n";
        $feed.= "        <title>".htmlspecialchars($this->title)."</title>\n";
        if ($this->pubDate!="") {
            $date = new FeedDate($this->pubDate);
            $feed.= "         <dateCreated>".$date->rfc822()."</dateCreated>\n";
        }
        if ($this->lastBuildDate!="") {
            $date = new FeedDate($this->lastBuildDate);
            $feed.= "         <dateModified>".$date->rfc822()."</dateModified>\n";
        }
        if ($this->editor!="") {
            $feed.= "         <ownerName>".$this->editor."</ownerName>\n";
        }
        if ($this->editorEmail!="") {
            $feed.= "         <ownerEmail>".$this->editorEmail."</ownerEmail>\n";
        }
        $feed.= "    </head>\n";
        $feed.= "    <body>\n";
        for ($i=0;$i<count($this->items);$i++) {
            $feed.= "    <outline type=\"rss\" ";
            $title = htmlspecialchars(strip_tags(strtr($this->items[$i]->title,"\n\r","  ")));
            $feed.= " title=\"".$title."\"";
            $feed.= " text=\"".$title."\"";
            //$feed.= " description=\"".htmlspecialchars($this->items[$i]->description)."\"";
            $feed.= " url=\"".htmlspecialchars($this->items[$i]->link)."\"";
            $feed.= "/>\n";
        }
        $feed.= "    </body>\n";
        $feed.= "</opml>\n";
        return $feed;
Andreas Gohr's avatar
Andreas Gohr committed
    }
Andreas Gohr's avatar
Andreas Gohr committed
 * HTMLCreator is a FeedCreator that writes an HTML feed file to a specific
andi's avatar
andi committed
 * location, overriding the createFeed method of the parent FeedCreator.
 * The HTML produced can be included over http by scripting languages, or serve
 * as the source for an IFrame.
 * All output by this class is embedded in <div></div> tags to enable formatting
Andreas Gohr's avatar
Andreas Gohr committed
 * using CSS.
andi's avatar
andi committed
 *
 * @author Pascal Van Hecke
 * @since 1.7
 */
class HTMLCreator extends FeedCreator {

    var $contentType = "text/html";
Andreas Gohr's avatar
Andreas Gohr committed

    /**
     * Contains HTML to be output at the start of the feed's html representation.
     */
    var $header;
Andreas Gohr's avatar
Andreas Gohr committed

    /**
     * Contains HTML to be output at the end of the feed's html representation.
     */
    var $footer ;
Andreas Gohr's avatar
Andreas Gohr committed

    /**
     * Contains HTML to be output between entries. A separator is only used in
     * case of multiple entries.
     */
    var $separator;
Andreas Gohr's avatar
Andreas Gohr committed

    /**
     * Used to prefix the stylenames to make sure they are unique
     * and do not clash with stylenames on the users' page.
     */
    var $stylePrefix;
Andreas Gohr's avatar
Andreas Gohr committed

    /**
     * Determines whether the links open in a new window or not.
     */
    var $openInNewWindow = true;
Andreas Gohr's avatar
Andreas Gohr committed

    var $imageAlign ="right";

    /**
     * In case of very simple output you may want to get rid of the style tags,
     * hence this variable.  There's no equivalent on item level, but of course you can
     * add strings to it while iterating over the items ($this->stylelessOutput .= ...)
     * and when it is non-empty, ONLY the styleless output is printed, the rest is ignored
     * in the function createFeed().
     */
    var $stylelessOutput ="";

    /**
     * Writes the HTML.
     * @return    string    the scripts's complete text
     */
    function createFeed() {
        // if there is styleless output, use the content of this variable and ignore the rest
        if ($this->stylelessOutput!="") {
            return $this->stylelessOutput;
Andreas Gohr's avatar
Andreas Gohr committed
        }

        //if no stylePrefix is set, generate it yourself depending on the script name
        if ($this->stylePrefix=="") {
            $this->stylePrefix = str_replace(".", "_", $this->_generateFilename())."_";
        }

        //set an openInNewWindow_token_to be inserted or not
        if ($this->openInNewWindow) {
            $targetInsert = " target='_blank'";
        }

        // use this array to put the lines in and implode later with "document.write" javascript
        $feedArray = array();
        if ($this->image!=null) {
            $imageStr = "<a href='".$this->image->link."'".$targetInsert.">".
                            "<img src='".$this->image->url."' border='0' alt='".
                            FeedCreator::iTrunc(htmlspecialchars($this->image->title),100).
                            "' align='".$this->imageAlign."' ";
            if ($this->image->width) {
                $imageStr .=" width='".$this->image->width. "' ";
            }
            if ($this->image->height) {
                $imageStr .=" height='".$this->image->height."' ";
            }
            $imageStr .="/></a>";
            $feedArray[] = $imageStr;
        }

        if ($this->title) {
            $feedArray[] = "<div class='".$this->stylePrefix."title'><a href='".$this->link."' ".$targetInsert." class='".$this->stylePrefix."title'>".
                FeedCreator::iTrunc(htmlspecialchars($this->title),100)."</a></div>";
        }
        if ($this->getDescription()) {
            $feedArray[] = "<div class='".$this->stylePrefix."description'>".
                str_replace("]]>", "", str_replace("<![CDATA[", "", $this->getDescription())).
                "</div>";
        }

        if ($this->header) {
            $feedArray[] = "<div class='".$this->stylePrefix."header'>".$this->header."</div>";
        }

        for ($i=0;$i<count($this->items);$i++) {
            if ($this->separator and $i > 0) {
                $feedArray[] = "<div class='".$this->stylePrefix."separator'>".$this->separator."</div>";
            }

            if ($this->items[$i]->title) {
                if ($this->items[$i]->link) {
                    $feedArray[] =
                        "<div class='".$this->stylePrefix."item_title'><a href='".$this->items[$i]->link."' class='".$this->stylePrefix.
                        "item_title'".$targetInsert.">".FeedCreator::iTrunc(htmlspecialchars(strip_tags($this->items[$i]->title)),100).
                        "</a></div>";
                } else {
                    $feedArray[] =
                        "<div class='".$this->stylePrefix."item_title'>".
                        FeedCreator::iTrunc(htmlspecialchars(strip_tags($this->items[$i]->title)),100).
                        "</div>";
                }
            }
            if ($this->items[$i]->getDescription()) {
                $feedArray[] =
                "<div class='".$this->stylePrefix."item_description'>".
                    str_replace("]]>", "", str_replace("<![CDATA[", "", $this->items[$i]->getDescription())).
                    "</div>";
            }
        }
        if ($this->footer) {
            $feedArray[] = "<div class='".$this->stylePrefix."footer'>".$this->footer."</div>";
        }

        $feed= "".join($feedArray, "\r\n");
        return $feed;
Andreas Gohr's avatar
Andreas Gohr committed
    }

    /**
     * Overrrides parent to produce .html extensions
     *
     * @return string the feed cache filename
     * @since 1.4
     * @access private
     */
    function _generateFilename() {
        $fileInfo = pathinfo($_SERVER["PHP_SELF"]);
        return substr($fileInfo["basename"],0,-(strlen($fileInfo["extension"])+1)).".html";
    }
Andreas Gohr's avatar
Andreas Gohr committed
}
andi's avatar
andi committed


/**
Andreas Gohr's avatar
Andreas Gohr committed
 * JSCreator is a class that writes a js file to a specific
andi's avatar
andi committed
 * location, overriding the createFeed method of the parent HTMLCreator.
 *
 * @author Pascal Van Hecke
 */
class JSCreator extends HTMLCreator {
    var $contentType = "text/javascript";
andi's avatar
andi committed

    /**
     * writes the javascript
     * @return    string    the scripts's complete text
     */
    function createFeed()
    {
        $feed = parent::createFeed();
        $feedArray = explode("\n",$feed);

        $jsFeed = "";
        foreach ($feedArray as $value) {
            $jsFeed .= "document.write('".trim(addslashes($value))."');\n";
        }
        return $jsFeed;
    }
andi's avatar
andi committed

    /**
     * Overrrides parent to produce .js extensions
     *
     * @return string the feed cache filename
     * @since 1.4
     * @access private
     */
    function _generateFilename() {
        $fileInfo = pathinfo($_SERVER["PHP_SELF"]);
        return substr($fileInfo["basename"],0,-(strlen($fileInfo["extension"])+1)).".js";
    }
andi's avatar
andi committed

andi's avatar
andi committed

/**
 * This class allows to override the hardcoded charset
 *
andi's avatar
andi committed
 * @author Andreas Gohr <andi@splitbrain.org>
andi's avatar
andi committed
 */
class DokuWikiFeedCreator extends UniversalFeedCreator{
    function createFeed($format = "RSS0.91",$encoding='iso-8859-15') {
        $this->_setFormat($format);
        $this->_feed->encoding = $encoding;
        return $this->_feed->createFeed();
    }
//Setup VIM: ex: et ts=4 enc=utf-8 :
?>