cvs: pear /File_Sitemap Sitemap.php package.xml /File_Sitemap/Sitemap Base.php Exception.php Index.php /File_Sitemap/examples sitemap_example.php /File_Sitemap/tests sitemap_add_remove.phpt sitemap_load_save.phpt sitemap_parse.phpt sitemap_test.phpt sitemap_validate.phpt sitemapindex_add_remove.phpt sitemapindex_load_save.phpt
[email protected] ("Charles Brunet")
| Newsgroups | php.pear.cvs |
|---|---|
| Message-ID | <cvscbrunet1210708763@cvsserver> |
cbrunet Tue May 13 19:59:23 2008 UTC
Added files:
/pear/File_Sitemap Sitemap.php package.xml
/pear/File_Sitemap/Sitemap Base.php Exception.php Index.php
/pear/File_Sitemap/examples sitemap_example.php
/pear/File_Sitemap/tests sitemap_add_remove.phpt
sitemap_load_save.phpt sitemap_parse.phpt
sitemap_test.phpt sitemap_validate.phpt
sitemapindex_add_remove.phpt
sitemapindex_load_save.phpt
Log:
Initial release.
cbrunet-20080513195923.txt
(text/plain, 41.7 KB)
http://cvs.php.net/viewvc.cgi/pear/File_Sitemap/Sitemap.php?view=markup&rev=1.1 Index: pear/File_Sitemap/Sitemap.php +++ pear/File_Sitemap/Sitemap.php <?php /* vim: set noai expandtab ts=4 st=4 sw=4: */ /** * Generate sitemap files. See http://www.sitemaps.org/protocol.php * for more details. * * PHP versions 5 * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * The names of its contributors may not be used to endorse or promote * products derived from this software without specific prior written * permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * * @category File * @package File_Sitemap * @author Charles Brunet <[email protected]> * @license http://www.opensource.org/licenses/bsd-license.html BSD License * @version CVS: $Id: Sitemap.php,v 1.1 2008/05/13 19:59:22 cbrunet Exp $ * @link http://pear.php.net/package/File_Sitemap */ require_once "File/Sitemap/Base.php"; /** * Generate sitemap files. See http://www.sitemaps.org/protocol.php * for more details. * * @category File * @package File_Sitemap * @author Charles Brunet <[email protected]> * @license http://www.opensource.org/licenses/bsd-license.html BSD License * @version Release: @package_version@ * @link http://pear.php.net/package/File_Sitemap */ class File_Sitemap extends File_Sitemap_Base { const SCHEMA = 'http://www.sitemaps.org/schemas/sitemap/0.9/sitemap.xsd'; /** * Constructor. Build an empty XML document, with xmlns and root element. * * @access public * @return void */ public function __construct() { parent::__construct('urlset', self::SCHEMA); } /** * Add or update a location in current sitemap * * @param mixed $loc string | array. URL (or array of URL). * Must contains protocol (http://) and trailling slash. * @param float $priority A number between 0.0 and 1.0 describing * relative priority. Default: 0.5 * @param string $changefreq Optional. Must be 'always', 'houly', 'daily', * 'weekly', 'monthly', 'yearly' or 'never'. * @param string $lastmod Optional. Date (and time) of last page * modification. * * @return void */ public function add($loc, $priority = 0.5, $changefreq = null, $lastmod = null) { if (!is_array($loc)) { $loc = array($loc); } foreach ($loc as $l) { // normalize and encode $l $l = $this->parseURL($l); // look for this url into the dom tree $url = $this->findLoc($l); if ($url === false) { // Create the url node, and append l node $url = $this->dom->createElementNS(self::XMLNS, 'url'); $elemLoc = $this->dom->createElementNS(self::XMLNS, 'loc', $l); $url->appendChild($elemLoc); } if ($priority !== null) { $priority = $this->parsePriority($priority); $this->updateNode($url, 'priority', $priority); } if ($changefreq !== null) { $changefreq = $this->parseChangefreq($changefreq); $this->updateNode($url, 'changefreq', $changefreq); } if ($lastmod !== null) { $lastmod = $this->parseDateTime($lastmod); $this->updateNode($url, 'lastmod', $lastmod); } $this->dom->documentElement->appendChild($url); } } /** * Ensure that priority is a number between 0.0 and 1.0 * * @param float $priority A number between 0.0 and 1.0 * * @return string * * @throws {@link File_Sitemap_Exception} Priority is not a number. */ protected function parsePriority($priority) { if (!is_numeric($priority)) { throw new File_Sitemap_Exception( 'priority must be a number between 0.0 and 1.0.', File_Sitemap_Exception::PARSE_ERROR); } $priority = (float) $priority; if ($priority > 1.0) { $priority = 1.0; } elseif ($priority < 0.0) { $priority = 0.0; } $priority = (string) $priority; // Apending .0 will ensure that 0 and 1 will give 0.0 and 1.0 $priority = substr($priority.'.0', 0, 3); return $priority; } /** * Ensure that $changefreq parameter is valid. * * @param string $changefreq A valid changefreq parameter: always, hourly, * daily, weekly, monthly, yearly or never. * * @return string * * @throws {@link File_Sitemap_Exception} changefreq not valid. */ protected function parseChangefreq($changefreq) { // I don't know why, but when changefreq === 0, it validates // if I don't do that... if ($changefreq === 0) { $changefreq = ''; } switch ($changefreq) { case 'always': case 'hourly': case 'daily': case 'weekly': case 'monthly': case 'yearly': case 'never': break; default: throw new File_Sitemap_Exception( 'changefreq must be one of always, hourly, daily, weekly, '. 'monthly, yearly or never.', File_Sitemap_Exception::PARSE_ERROR); } return $changefreq; } /** * Validate sitemap against its schema definition. * * @return boolean */ public function validate() { return parent::validate(self::SCHEMA); } } ?> http://cvs.php.net/viewvc.cgi/pear/File_Sitemap/package.xml?view=markup&rev=1.1 Index: pear/File_Sitemap/package.xml +++ pear/File_Sitemap/package.xml <?xml version="1.0" encoding="UTF-8"?> <package packagerversion="1.7.1" version="2.0" xmlns="http://pear.php.net/dtd/package-2.0" xmlns:tasks="http://pear.php.net/dtd/tasks-1.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://pear.php.net/dtd/tasks-1.0 http://pear.php.net/dtd/tasks-1.0.xsd http://pear.php.net/dtd/package-2.0 http://pear.php.net/dtd/package-2.0.xsd"> <name>File_Sitemap</name> <channel>pear.php.net</channel> <summary>Create and manage sitemap files.</summary> <description>This package allow to create sitemap files used to describe your website to help search engines indexing it. This package contains all needed functions to create, read, save, add, modify and remove url, compress to gzip, notify search engine and test url in the sitemap or sitemap index. </description> <lead> <name>Charles Brunet</name> <user>cbrunet</user> <email>[email protected]</email> <active>yes</active> </lead> <date>2008-05-13</date> <time>13:26:00</time> <version> <release>0.1.2</release> <api>0.9</api> </version> <stability> <release>alpha</release> <api>alpha</api> </stability> <license uri="http://www.opensource.org/licenses/bsd-license.html"> BSD License</license> <notes>First release. </notes> <contents> <dir name="/" baseinstalldir="File"> <file name="Sitemap.php" role="php"> <tasks:replace from="@package_version@" to="version" type="package-info" /> </file> <dir name="Sitemap"> <file name="Index.php" role="php"> <tasks:replace from="@package_version@" to="version" type="package-info" /> </file> <file name="Exception.php" role="php"> <tasks:replace from="@package_version@" to="version" type="package-info" /> </file> <file name="Base.php" role="php"> <tasks:replace from="@package_version@" to="version" type="package-info" /> </file> </dir> <dir name="tests"> <file name="sitemap_add_remove.phpt" role="test"/> <file name="sitemap_load_save.phpt" role="test"/> <file name="sitemapindex_add_remove.phpt" role="test"/> <file name="sitemapindex_load_save.phpt" role="test"/> <file name="sitemap_validate.phpt" role="test"/> <file name="sitemap_parse.phpt" role="test"/> <file name="sitemap_test.phpt" role="test"/> </dir> <dir name="examples"> <file name="sitemap_example.php" role="doc"/> </dir> </dir> </contents> <dependencies> <required> <php> <min>5.0.0</min> </php> <pearinstaller> <min>1.4.0b1</min> </pearinstaller> <extension> <name>zlib</name> </extension> </required> <optional> <package> <name>HTTP_Request</name> <channel>pear.php.net</channel> </package> </optional> </dependencies> <phprelease /> </package> http://cvs.php.net/viewvc.cgi/pear/File_Sitemap/Sitemap/Base.php?view=markup&rev=1.1 Index: pear/File_Sitemap/Sitemap/Base.php +++ pear/File_Sitemap/Sitemap/Base.php <?php /* vim: set noai expandtab ts=4 st=4 sw=4: */ /** * Abstract class providing common functions to File_Sitemap related classes. * * PHP versions 5 * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * The names of its contributors may not be used to endorse or promote * products derived from this software without specific prior written * permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * * @category File * @package File_Sitemap * @author Charles Brunet <[email protected]> * @license http://www.opensource.org/licenses/bsd-license.html BSD License * @version CVS: $Id: Base.php,v 1.1 2008/05/13 19:59:22 cbrunet Exp $ * @link http://pear.php.net/package/File_Sitemap */ require_once "File/Sitemap/Exception.php"; /** * Abstract class providing common functions to File_Sitemap related classes. * * @category File * @package File_Sitemap * @author Charles Brunet <[email protected]> * @license http://www.opensource.org/licenses/bsd-license.html BSD License * @version Release: @package_version@ * @link http://pear.php.net/package/File_Sitemap */ abstract class File_Sitemap_Base { /** * The internal DOMDocument used by this class * * @var DOMDocument */ protected $dom; /** * XML namespace */ const XMLNS = 'http://www.sitemaps.org/schemas/sitemap/0.9'; /** * namespace of XMLSchema-instance */ const XSI = 'http://www.w3.org/2001/XMLSchema-instance'; /** * Constructor. Build an empty XML document, with xmlns and root element. * * @param string $root Name of the root element * @param string $schema Location of the schema * * @return void */ public function __construct($root, $schema) { $imp = new DomImplementation(); $this->dom = $imp->createDocument(self::XMLNS, $root); $this->dom->version = '1.0'; $this->dom->encoding = 'UTF-8'; $attr = $this->dom->createAttributeNS(self::XSI, 'xsi:schemaLocation'); $attr->value = self::XMLNS.' '.$schema; $this->dom->documentElement->appendChild($attr); } /** * Returns the DOMNode element which contains $url, or false if not found. * * @param string $url URL (loc) we are looking for. * * @return mixed DOMNode | false */ protected function findLoc($url) { foreach ($this->dom->getElementsByTagNameNS(self::XMLNS, 'loc') as $urlElem) { if ($urlElem->nodeValue == $url) { return $urlElem->parentNode; } } return false; } /** * Set to $nodeValue the value of the $nodeName child of $urlNode. * * If $urlNode doen't have a $nodeName child, add it. * * @param DOMNode $urlNode The parent of the node we want to update. * @param string $nodeName The name of the node we want to update. * @param string $nodeVal The value we want to put into the node. * * @return void */ protected function updateNode($urlNode, $nodeName, $nodeVal) { $exists = false; // replace old priority if it exists foreach ($urlNode->childNodes as $child) { if ($child->nodeName == $nodeName) { $child->nodeValue = $nodeVal; return; } } // If we found a value, function returns. // If we are here, then the node wasn't find. $elem = $this->dom->createElementNS(self::XMLNS, $nodeName, $nodeVal); $urlNode->appendChild($elem); } /** * Used as callback function to preg_replace_callback to urlencode char * * @param array $char $char[0] will be encoded * * @return string */ private static function _myUrlEncode($char) { return rawurlencode($char[0]); } /** * Ensure url contains valid chars and isn't longer than 2048 chars. * * urlencode invalid chars. Convert invalid XML chars to entities. * * @param string $url The url we want to verify and encode. * * @return string * * @throws {@link File_Sitemap_Exception} URL doesn't begin with valid * protocol (http, https, ftp) or encoded URL longer than 2048 chars. */ protected function parseURL($url) { $protocols = array('http', 'https', 'ftp', ); if (!preg_match('/^('.implode($protocols, ':\/\/|').':\/\/)/', $url)) { throw new File_Sitemap_Exception( 'URL must begin with a protocol ('. implode($protocols, ', ').').', File_Sitemap_Exception::PARSE_ERROR); } // encode XML special chars $url = strtr($url, array('&'=>'&', '\''=>''', '"'=>'"', '>'=>'>', '<'=>'<', )); // replace other chars with %nn form $url = preg_replace_callback('/[^0-9a-zA-Z_'. ':\/?#\[\]@!$&\'()*+,;=%~.-]/', 'File_Sitemap_Base::_myUrlEncode', $url); if (strlen($url) > 2048) { throw new File_Sitemap_Exception( 'URL must not be longer than 2048 chars.', File_Sitemap_Exception::PARSE_ERROR); } return $url; } /** * Ensure that $datetime is a valid date time string * * If $datetime is conform to the spec, it is returned as is. * Else we try to decode it using strtotime function. * * @param string $datetime The date (and time) to pase. * * @return string * * @see http://www.w3.org/TR/NOTE-datetime * @throws {@link File_Sitemap_Exception} Indalid date / time format. */ protected function parseDateTime($datetime) { if (preg_match('/^\d{4}(-\d{2}(-\d{2}(T\d{2}:\d{2}(:\d{2}(\.\d+)?)?'. '([+-]\d{2}:\d{2}|Z))?)?)?$/', $datetime)) { return $datetime; } // Try to convert it $timestamp = @strtotime($datetime); if ($timestamp === false) { throw new File_Sitemap_Exception( 'unable to parse date time string.', File_Sitemap_Exception::PARSE_ERROR); } $datetime = date('Y-m-d\TH:i:sP', $timestamp); return $datetime; } /** * Remove DOMNode that contains url $loc from the document. * * @param string $loc URL to remove * * @return void */ public function remove($loc) { $loc = $this->parseURL($loc); $urlNode = $this->findLoc($loc); if ($urlNode !== false) { $this->dom->documentElement->removeChild($urlNode); } } /** * Load sitemap from file. The file can be gzipped or not. * * @param string $file Filename (or URL). * * @return void * * @throws {@link File_Sitemap_Exception} File read error. */ public function load($file) { if (substr($file, -2) == 'gz') { $gzfile = gzopen($file, 'r'); if ($gzfile === false) { throw new File_Sitemap_Exception( 'error opening gziped sitemap file.', File_Sitemap_Exception::FILE_ERROR); } $xml = ''; while (!gzeof($gzfile)) { $xml .= gzread($gzfile, 10000); } gzclose($gzfile); $this->dom->loadXML($xml); } else { $this->dom->load($file); } } /** * Save sitemap to file. * * @param string $file Filename (or URL), including path. * @param boolean $compress gzip the file? Default true. * @param boolean $formatOutput Nice format XML. Default false. * * @return void * * @throws {@link File_Sitemap_Exception} File write error. */ public function save($file, $compress = true, $formatOutput = false) { $this->dom->formatOutput = $formatOutput; if ($compress) { if (substr($file, -3) != '.gz') { $file .= '.gz'; } $gzfile = gzopen($file, 'w9'); if ($gzfile === false) { throw new File_Sitemap_Exception( 'error saving gziped sitemap file.', File_Sitemap_Exception::FILE_ERROR); } gzwrite($gzfile, $this->dom->saveXML()); gzclose($gzfile); } else { $this->dom->save($file); } } /** * Notify $site that a sitemap was updated at $url * * @param string $url URL of the sitemap file (must be valid) * @param mixed $site string | array. URL (or array of URL) of the search * engine ping site * * @return void * * @throws {@link File_Sitemap_Exception} Sitemap file not reachable * or ping site error. */ public function notify($url, $site = 'http://www.google.com/webmasters/sitemaps/ping') { include_once 'HTTP/Request.php'; // check that $url exists $req = new HTTP_Request(''); $req->setURL($url); $req->sendRequest(); $code = $req->getResponseCode(); switch ($code) { case 200: // Everything ok! break; default: throw new File_Sitemap_Exception( 'Cannot reach sitemap file. Error: '.$code, File_Sitemap_Exception::ERROR + $code); } // Ping the web search engine if (!is_array($site)) { $site = array($site); } $req->setMethod(HTTP_REQUEST_METHOD_GET); foreach ($site as $s) { $req->setURL($s); $req->addQueryString('sitemap', $url); $req->sendRequest(); $code = $req->getResponseCode(); if ($code != 200) { throw new File_Sitemap_Exception( 'Cannot reach '.$s.'. Error: '.$code, File_Sitemap_Exception::ERROR + $code); } } } /** * Test that all url in sitemap are valid URL * * @param array &$results An array that will contains result codes. * key is the url, value is the response code (200, 302, 404, etc.) * * @return boolean true if all URLs reached */ public function test(&$results = array()) { include_once 'HTTP/Request.php'; $req = new HTTP_Request(''); $allok = true; $urllist = $this->dom->getElementsByTagNameNS(self::XMLNS, 'loc'); foreach ($urllist as $urlnode) { $url = html_entity_decode($urlnode->nodeValue); $req->setURL($url); $req->sendRequest(); $code = $req->getResponseCode(); $results[$url] = $code; if ($code >= 400) { $allok = false; } } return $allok; } /** * Validate the sitemap document against DTD * * Be warned that it will issue some warnings if it doesn't validate. * * @param string $schema URL of the validating schema. * * @return boolean */ public function validate($schema) { return $this->dom->schemaValidate($schema); } } ?> http://cvs.php.net/viewvc.cgi/pear/File_Sitemap/Sitemap/Exception.php?view=markup&rev=1.1 Index: pear/File_Sitemap/Sitemap/Exception.php +++ pear/File_Sitemap/Sitemap/Exception.php <?php /* vim: set noai expandtab ts=4 st=4 sw=4: */ /** * Exception class used by File_Sitemap package. * * PHP versions 5 * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * The names of its contributors may not be used to endorse or promote * products derived from this software without specific prior written * permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * * @category File * @package File_Sitemap * @author Charles Brunet <[email protected]> * @license http://www.opensource.org/licenses/bsd-license.html BSD License * @version CVS: $Id: Exception.php,v 1.1 2008/05/13 19:59:22 cbrunet Exp $ * @link http://pear.php.net/package/File_Sitemap */ require_once "PEAR/Exception.php"; /** * Exeption class for the File_Sitemap package. * * @category File * @package File_Sitemap * @author Charles Brunet <[email protected]> * @license http://www.opensource.org/licenses/bsd-license.html BSD License * @version Release: 0.1.1 * @link http://pear.php.net/package/File_Sitemap */ class File_Sitemap_Exception extends PEAR_Exception { /** * Misc errors. Can be added to HTTP response code. 1404 means page not * found. */ const ERROR = 1000; /** * Error relative to argument parsing when adding data to sitemap. */ const PARSE_ERROR = 2000; /** * File related error when reading or writing sitemap file. */ const FILE_ERROR = 3000; } ?> http://cvs.php.net/viewvc.cgi/pear/File_Sitemap/Sitemap/Index.php?view=markup&rev=1.1 Index: pear/File_Sitemap/Sitemap/Index.php +++ pear/File_Sitemap/Sitemap/Index.php <?php /* vim: set noai expandtab ts=4 st=4 sw=4: */ /** * Generate sitemap index file. * * PHP versions 5 * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * The names of its contributors may not be used to endorse or promote * products derived from this software without specific prior written * permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * * @category File * @package File_Sitemap * @author Charles Brunet <[email protected]> * @license http://www.opensource.org/licenses/bsd-license.html BSD License * @version CVS: $Id: Index.php,v 1.1 2008/05/13 19:59:22 cbrunet Exp $ * @link http://pear.php.net/package/File_Sitemap */ require_once "File/Sitemap/Base.php"; /** * Generate sitemap index file. * * @category File * @package File_Sitemap * @author Charles Brunet <[email protected]> * @license http://www.opensource.org/licenses/bsd-license.html BSD License * @version Release: @package_version@ * @link http://pear.php.net/package/File_Sitemap */ class File_Sitemap_Index extends File_Sitemap_Base { /** * URL of XML schema */ const SCHEMA = 'http://www.sitemaps.org/schemas/sitemap/0.9/siteindex.xsd'; /** * Constructor. * * @return void */ public function __construct() { parent::__construct('sitemapindex', self::SCHEMA); } /** * Add a sitemap to the sitemapindex. * * @param mixed $loc string | array. URL (or array of URL) of the * sitemap file. * @param mixed $lastmod Date (and time) of last modification (optional). * * @return void */ public function add($loc, $lastmod = null) { if (!is_array($loc)) { $loc = array($loc); } foreach ($loc as $l) { // normalize and encode $loc $l = $this->parseURL($l); // look for this url into the dom tree $sitemap = $this->findLoc($l); if ($sitemap === false) { // Create the url node, and append loc node $sitemap = $this->dom->createElementNS(self::XMLNS, 'sitemap'); $elemLoc = $this->dom->createElementNS(self::XMLNS, 'loc', $l); $sitemap->appendChild($elemLoc); $newURL = true; } else { $newURL = false; } if ($lastmod !== null) { $lastmod = $this->_parseDateTime($lastmod); $this->updateNode($sitemap, 'lastmod', $lastmod); } $this->dom->documentElement->appendChild($sitemap); } } /** * Validate sitemap index with the schema definition. * * @return boolean */ public function validate() { return parent::validate(self::SCHEMA); } } ?> http://cvs.php.net/viewvc.cgi/pear/File_Sitemap/examples/sitemap_example.php?view=markup&rev=1.1 Index: pear/File_Sitemap/examples/sitemap_example.php +++ pear/File_Sitemap/examples/sitemap_example.php <?php require_once "File/Sitemap.php"; require_once "File/Sitemap/Index.php"; // Since dom is a protected member, we create // this little utility class to show an example // of the generated output. class Sitemap_Example extends File_Sitemap { function output() { $this->dom->formatOutput = true; $sm = $this->dom->saveXML(); $sm = htmlentities($sm); echo "<pre>"; echo $sm; echo "</pre>\n"; } } // Create sitemap object // $sm = new File_Sitemap(); $sm = new Sitemap_Example(); // Let define some urls $baseurl = 'http://pear.php.net'; $urls = array('/', '/packages.php', '/manual/', '/manual/en/', '/manual/en/preface.php', '/pepr/', '/pepr/pepr-proposal-show.php?id=555', ); // A function to generate an arbitrary priority number... function priority($url) { $a = array(); $n = 0; $n += preg_match_all('/\.php/', $url, $a); // url contains .php $n += preg_match_all('/\//', $url, $a); // number of / $n += preg_match_all('/\?/', $url, $a); // url contains ? $p = 1 / $n; return $p; } // Add urls to our sitemap foreach ($urls as $url) { $sm->add($baseurl.$url, priority($url)); } // Add some precisions for specific pages $sm->add($baseurl.'/', NULL, 'daily'); $sm->add($baseurl.'/manual/', NULL, 'weekly'); // Validate our sitemap (not really needed is we used the API to generate it!) // $sm->validate(); // Test validity of all urls in the sitemap // This could take a very long time if sitemap is huge... // $sm->test(); // Save sitemap to compressed file // $sm->save('/path/to/web/root/sitemap1.gz'); // Notify Google about our sitemap update // $sm->notify('http://my.web.site/sitemap1.gz'); // This is our sitemap: (output is not a function of File_Sitemap class!) $sm->output(); // Not an example with sitemap index $smi = new File_Sitemap_Index(); $sitemaps = array('http://my.web.site/sitemap1.gz', 'http://my.web.site/sitemap2.gz', 'http://my.web.site/sitemap3.gz', ); $smi->add($sitemaps); // It's a good idea to ensure that all sitemaps are reacheable... // $smi->test(); // Save the sitemap index // $smi->save('/path/to/wesite/root/sitemap.gz') ?> http://cvs.php.net/viewvc.cgi/pear/File_Sitemap/tests/sitemap_add_remove.phpt?view=markup&rev=1.1 Index: pear/File_Sitemap/tests/sitemap_add_remove.phpt +++ pear/File_Sitemap/tests/sitemap_add_remove.phpt --TEST-- File_Sitemap: Add and remove url from sitemap. --FILE-- <?php require_once "File/Sitemap.php"; try { $sm = new File_Sitemap(); $sm->add("http://pear.php.net/"); $sm->add("http://pear.php.net/pepr/"); $sm->add("http://pear.php.net/packages.php"); $sm->remove("http://pear.php.net/pepr/"); $filename = tempnam("/tmp", "sitemap").".xml"; $sm->save($filename, false, true); $f = fopen($filename, 'r'); if ($f === false) { throw new Exception("Cannot open file"); } while (!feof($f)) { echo fread($f, 10000); } fclose($f); unlink($filename); } catch (Exception $e) { echo $e->getMessage(); } ?> --EXPECT-- <?xml version="1.0" encoding="UTF-8"?> <urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.sitemaps.org/schemas/sitemap/0.9 http://www.sitemaps.org/schemas/sitemap/0.9/sitemap.xsd"> <url> <loc>http://pear.php.net/</loc> <priority>0.5</priority> </url> <url> <loc>http://pear.php.net/packages.php</loc> <priority>0.5</priority> </url> </urlset> http://cvs.php.net/viewvc.cgi/pear/File_Sitemap/tests/sitemap_load_save.phpt?view=markup&rev=1.1 Index: pear/File_Sitemap/tests/sitemap_load_save.phpt +++ pear/File_Sitemap/tests/sitemap_load_save.phpt --TEST-- File_Sitemap: Test sitemap file writing and reading --FILE-- <?php require_once "File/Sitemap.php"; try { $sm = new File_Sitemap(); $sm->add("http://pear.php.net/"); $sm->add("http://pear.php.net/pepr/"); $sm->add("http://pear.php.net/packages.php"); $filename = tempnam("/tmp", "sitemap").".xml"; $filename2 = tempnam("/tmp", "sitemap").".gz"; $filename3 = tempnam("/tmp", "sitemap").".xml"; $filename4 = tempnam("/tmp", "sitemap").".gz"; $sm->save($filename, false); $sm->save($filename2, true); $sm3 = new File_Sitemap(); $sm3->load($filename); $sm3->save($filename3, false); $sm4 = new File_Sitemap(); $sm4->load($filename2); $sm4->save($filename4, true); if (md5_file($filename) == md5_file($filename3)) { echo "Plain: passed!\n"; } else { echo "Plain: failed...\n"; } if (md5_file($filename2) == md5_file($filename4)) { echo "Gzipped: passed!"; } else { echo "Gzipped: failed..."; } unlink($filename); unlink($filename2); unlink($filename3); unlink($filename4); } catch (Exception $e) { echo $e->getMessage(); } ?> --EXPECT-- Plain: passed! Gzipped: passed! http://cvs.php.net/viewvc.cgi/pear/File_Sitemap/tests/sitemap_parse.phpt?view=markup&rev=1.1 Index: pear/File_Sitemap/tests/sitemap_parse.phpt +++ pear/File_Sitemap/tests/sitemap_parse.phpt --TEST-- File_Sitemap: Validate different possible input parameters. --FILE-- <?php require_once "File/Sitemap.php"; $sm = new File_Sitemap(); echo "1 validate loc\n--------------------\n"; $u = array('http://www.php.net/', 'ftp://ftp.php.net/file.txt', 'https://secure.php.net/', 'http://pear.php.net/manual/en/core.pear.pear-exception.intro.php', 'http://mysite.net/caractères_spéciaux.php', 'http://mysite.net/query.php?a=0&b=1&c=4', 'www.google.com', 'abcde', 'rsync:///myserver.net'); foreach ($u as $uu) { echo $uu.": "; try { $sm->add($uu); echo "OK\n"; } catch (File_Sitemap_Exception $e) { echo "Exception: ".$e->getCode().": ".$e->getMessage()."\n"; } } echo "2 validate lastmod\n--------------------\n"; $lm = array('2008', '2008-04', '2008-04-12', '2008-04-12T18:20Z', '2008-04-12T18:20+05:00', '2008-04-12T18:20:31-04:00', '2008-04-12T18:20:31.118-04:00', 'Apr. 12, 2008', '20h27', 'abcdef'); foreach ($lm as $lmlm) { echo $lmlm.": "; try { $sm->add("http://www.php.net/", 0.5, null, $lmlm); echo "OK\n"; } catch (File_Sitemap_Exception $e) { echo "Exception: ".$e->getCode().": ".$e->getMessage()."\n"; } } echo "3 validate changefreq\n--------------------\n"; $cf = array('always', 'hourly', 'daily', 'weekly', 'monthly', 'yearly', 'never', 0, 'stchroumph'); foreach ($cf as $cfcf) { echo $cfcf.": "; try { $sm->add("http://www.php.net/", 0.5, $cfcf); echo "OK\n"; } catch (File_Sitemap_Exception $e) { echo "Exception: ".$e->getCode().": ".$e->getMessage()."\n"; } } echo "4 validate priority\n--------------------\n"; $p = array(-1, 0, 0.5, 0.8, 1, 2, "-1", "0", "0.0", ".5", "0.85", "1.2", "a"); foreach ($p as $pp) { echo $pp.": "; try { $sm->add("http://www.php.net/", $pp); echo "OK\n"; } catch (File_Sitemap_Exception $e) { echo "Exception: ".$e->getCode().": ".$e->getMessage()."\n"; } } ?> --EXPECT-- 1 validate loc -------------------- http://www.php.net/: OK ftp://ftp.php.net/file.txt: OK https://secure.php.net/: OK http://pear.php.net/manual/en/core.pear.pear-exception.intro.php: OK http://mysite.net/caractères_spéciaux.php: OK http://mysite.net/query.php?a=0&b=1&c=4: OK www.google.com: Exception: 2000: URL must begin with a protocol (http, https, ftp). abcde: Exception: 2000: URL must begin with a protocol (http, https, ftp). rsync:///myserver.net: Exception: 2000: URL must begin with a protocol (http, https, ftp). 2 validate lastmod -------------------- 2008: OK 2008-04: OK 2008-04-12: OK 2008-04-12T18:20Z: OK 2008-04-12T18:20+05:00: OK 2008-04-12T18:20:31-04:00: OK 2008-04-12T18:20:31.118-04:00: OK Apr. 12, 2008: OK 20h27: Exception: 2000: unable to parse date time string. abcdef: Exception: 2000: unable to parse date time string. 3 validate changefreq -------------------- always: OK hourly: OK daily: OK weekly: OK monthly: OK yearly: OK never: OK 0: Exception: 2000: changefreq must be one of always, hourly, daily, weekly, monthly, yearly or never. stchroumph: Exception: 2000: changefreq must be one of always, hourly, daily, weekly, monthly, yearly or never. 4 validate priority -------------------- -1: OK 0: OK 0.5: OK 0.8: OK 1: OK 2: OK -1: OK 0: OK 0.0: OK..5: OK 0.85: OK 1.2: OK a: Exception: 2000: priority must be a number between 0.0 and 1.0. http://cvs.php.net/viewvc.cgi/pear/File_Sitemap/tests/sitemap_test.phpt?view=markup&rev=1.1 Index: pear/File_Sitemap/tests/sitemap_test.phpt +++ pear/File_Sitemap/tests/sitemap_test.phpt --TEST-- File_Sitemap: Test URLs of sitemap --FILE-- <?php require_once "File/Sitemap.php"; try { $sm = new File_Sitemap(); $sm->add("http://pear.php.net/"); $sm->add("http://pear.php.net/pepr/"); $sm->add("http://pear.php.net/packages.php"); $results = array(); $sm->test($results); print_r($results); } catch (Exception $e) { echo $e->getMessage(); } ?> --EXPECT-- Array ( [http://pear.php.net/] => 200 [http://pear.php.net/pepr/] => 200 [http://pear.php.net/packages.php] => 200 ) http://cvs.php.net/viewvc.cgi/pear/File_Sitemap/tests/sitemap_validate.phpt?view=markup&rev=1.1 Index: pear/File_Sitemap/tests/sitemap_validate.phpt +++ pear/File_Sitemap/tests/sitemap_validate.phpt --TEST-- File_Sitemap: Test URLs of sitemap --FILE-- <?php require_once "File/Sitemap.php"; require_once "File/Sitemap/Index.php"; try { $sm = new File_Sitemap(); $sm->add("http://pear.php.net/"); $sm->add("http://pear.php.net/pepr/"); $sm->add("http://pear.php.net/packages.php"); $result = $sm->validate(); if ($result) { echo "Sitemap valid!\n"; } else { echo "Sitemap not validated...\n"; } $smi = new File_Sitemap_Index(); $smi->add("http://mysite.net/sitemap1.gz"); $smi->add("http://mysite.net/sitemap2.gz"); $smi->add("http://mysite.net/sitemap3.gz"); $result = $smi->validate(); if ($result) { echo "Sitemap index valid!\n"; } else { echo "Sitemap index not validated...\n"; } } catch (Exception $e) { echo $e->getMessage(); } ?> --EXPECT-- Sitemap valid! Sitemap index valid! http://cvs.php.net/viewvc.cgi/pear/File_Sitemap/tests/sitemapindex_add_remove.phpt?view=markup&rev=1.1 Index: pear/File_Sitemap/tests/sitemapindex_add_remove.phpt +++ pear/File_Sitemap/tests/sitemapindex_add_remove.phpt --TEST-- File_Sitemap: Add and remove url from sitemap index. --FILE-- <?php require_once "File/Sitemap/Index.php"; try { $sm = new File_Sitemap_Index(); $sm->add("http://mysite.net/sitemap1.gz"); $sm->add("http://mysite.net/sitemap2.gz"); $sm->add("http://mysite.net/sitemap3.gz"); $sm->remove("http://mysite.net/sitemap2.gz"); $filename = tempnam("/tmp", "sitemapindex").".xml"; $sm->save($filename, false, true); $f = fopen($filename, 'r'); if ($f === false) { throw new Exception("Cannot open file"); } while (!feof($f)) { echo fread($f, 10000); } fclose($f); unlink($filename); } catch (Exception $e) { echo $e->getMessage(); } ?> --EXPECT-- <?xml version="1.0" encoding="UTF-8"?> <sitemapindex xmlns="http://www.sitemaps.org/schemas/sitemap/0.9" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.sitemaps.org/schemas/sitemap/0.9 http://www.sitemaps.org/schemas/sitemap/0.9/siteindex.xsd"> <sitemap> <loc>http://mysite.net/sitemap1.gz</loc> </sitemap> <sitemap> <loc>http://mysite.net/sitemap3.gz</loc> </sitemap> </sitemapindex> http://cvs.php.net/viewvc.cgi/pear/File_Sitemap/tests/sitemapindex_load_save.phpt?view=markup&rev=1.1 Index: pear/File_Sitemap/tests/sitemapindex_load_save.phpt +++ pear/File_Sitemap/tests/sitemapindex_load_save.phpt --TEST-- File_Sitemap: Test sitemap index file writing and reading --FILE-- <?php require_once "File/Sitemap/Index.php"; try { $sm = new File_Sitemap_Index(); $sm->add("http://mysite.net/sitemap1.gz"); $sm->add("http://mysite.net/sitemap2.gz"); $sm->add("http://mysite.net/sitemap3.gz"); $filename = tempnam("/tmp", "sitemap").".xml"; $filename2 = tempnam("/tmp", "sitemap").".gz"; $filename3 = tempnam("/tmp", "sitemap").".xml"; $filename4 = tempnam("/tmp", "sitemap").".gz"; $sm->save($filename, false); $sm->save($filename2, true); $sm3 = new File_Sitemap_Index(); $sm3->load($filename); $sm3->save($filename3, false); $sm4 = new File_Sitemap_Index(); $sm4->load($filename2); $sm4->save($filename4, true); if (md5_file($filename) == md5_file($filename3)) { echo "Plain: passed!\n"; } else { echo "Plain: failed...\n"; } if (md5_file($filename2) == md5_file($filename4)) { echo "Gzipped: passed!"; } else { echo "Gzipped: failed..."; } unlink($filename); unlink($filename2); unlink($filename3); unlink($filename4); } catch (Exception $e) { echo $e->getMessage(); } ?> --EXPECT-- Plain: passed! Gzipped: passed!