http location to final sitemap file, fileName -> full server path to sitemap file, _appid -> yahoo! api id
//sure this can be cleaned up - but for the point of it - do whatever you need.
//this is a generic reproduction of the wordpress google sitemap generator - not intended for actual out-of-the-box use.
//$gen = new GoogleSitemapGenerator();
//$gen->BuildSitemap();
//TODO - you need snoopy for pings
require_once('class-snoopy.php');
//error_reporting(E_ALL);
//ini_set("display_errors",1);
//@ini_set("memory_limit",'');
/**
* Represents an item in the page list
* @author Arne Brachhold
* @package sitemap
* @since 3.0
*/
class GoogleSitemapGeneratorPage {
/**
* @var string $_url Sets the URL or the relative path to the blog dir of the page
* @access private
*/
var $_url;
/**
* @var float $_priority Sets the priority of this page
* @access private
*/
var $_priority;
/**
* @var string $_changeFreq Sets the change frequency of the page. I want Enums!
* @access private
*/
var $_changeFreq;
/**
* @var int $_lastMod Sets the lastMod date as a UNIX timestamp.
* @access private
*/
var $_lastMod;
/**
* Initialize a new page object
*
* @since 3.0
* @access public
* @author Arne Brachhold
* @param bool $enabled Should this page be included in thesitemap
* @param string $url The URL or path of the file
* @param float $priority The Priority of the page 0.0 to 1.0
* @param string $changeFreq The change frequency like daily, hourly, weekly
* @param int $lastMod The last mod date as a unix timestamp
*/
function GoogleSitemapGeneratorPage($url="",$priority=0.0,$changeFreq="never",$lastMod=0) {
$this->SetUrl($url);
$this->SetProprity($priority);
$this->SetChangeFreq($changeFreq);
$this->SetLastMod($lastMod);
}
/**
* Returns the URL of the page
*
* @return string The URL
*/
function GetUrl() {
return $this->_url;
}
/**
* Sets the URL of the page
*
* @param string $url The new URL
*/
function SetUrl($url) {
$this->_url=(string) $url;
}
/**
* Returns the priority of this page
*
* @return float the priority, from 0.0 to 1.0
*/
function GetPriority() {
return $this->_priority;
}
/**
* Sets the priority of the page
*
* @param float $priority The new priority from 0.1 to 1.0
*/
function SetProprity($priority) {
$this->_priority=floatval($priority);
}
/**
* Returns the change frequency of the page
*
* @return string The change frequncy like hourly, weekly, monthly etc.
*/
function GetChangeFreq() {
return $this->_changeFreq;
}
/**
* Sets the change frequency of the page
*
* @param string $changeFreq The new change frequency
*/
function SetChangeFreq($changeFreq) {
$this->_changeFreq=(string) $changeFreq;
}
/**
* Returns the last mod of the page
*
* @return int The lastmod value in seconds
*/
function GetLastMod() {
return $this->_lastMod;
}
/**
* Sets the last mod of the page
*
* @param int $lastMod The lastmod of the page
*/
function SetLastMod($lastMod) {
$this->_lastMod=intval($lastMod);
}
function Render() {
if($this->_url == "/" || empty($this->_url)) return '';
$r="";
$r.= "\t\n";
$r.= "\t\t" . $this->EscapeXML($this->_url) . "\n";
if($this->_lastMod>0) $r.= "\t\t" . date('Y-m-d\TH:i:s+00:00',$this->_lastMod) . "\n";
if(!empty($this->_changeFreq)) $r.= "\t\t" . $this->_changeFreq . "\n";
if($this->_priority!==false && $this->_priority!=="") $r.= "\t\t" . number_format($this->_priority,1) . "\n";
$r.= "\t\n";
return $r;
}
function EscapeXML($string) {
return str_replace ( array ( '&', '"', "'", '<', '>'), array ( '&' , '"', ''' , '<' , '>'), $string);
}
}
class GoogleSitemapGeneratorXmlEntry {
var $_xml;
function GoogleSitemapGeneratorXmlEntry($xml) {
$this->_xml = $xml;
}
function Render() {
return $this->_xml;
}
}
class GoogleSitemapGeneratorDebugEntry extends GoogleSitemapGeneratorXmlEntry {
function Render() {
return "\n";
}
}
/**
* Class to generate a sitemaps.org Sitemaps compliant sitemap of a WordPress blog.
*
* @package sitemap
* @author Arne Brachhold
* @since 3.0
*/
class GoogleSitemapGenerator {
/**
* @var string Holds the last error if one occurs when writing the files
*/
var $_lastError=null;
/**
* @var object The file handle which is used to write the sitemap file
*/
var $_fileHandle = null;
/**
* @var object The file handle which is used to write the zipped sitemap file
*/
var $_fileZipHandle = null;
/**
* @var string $_appid Sets the Yahoo! appid
* @access private
*/
var $_appid = null; //but you sould probably set this to something of value from yahoo!
/**
* Initializes a new Google Sitemap Generator
*
* @since 3.0
* @access private
* @author Arne Brachhold
*/
function GoogleSitemapGenerator() {
}
/**
* Returns if the compressed sitemap was activated
*
* @since 3.0b8
* @access private
* @author Arne Brachhold
* @return true if compressed
*/
function IsGzipEnabled() {
return (function_exists("gzwrite"));
}
/**
* Adds a url to the sitemap. You can use this method or call AddElement directly.
*
* @since 3.0
* @access public
* @author Arne Brachhold
* @param $loc string The location (url) of the page
* @param $lastMod int The last Modification time as a UNIX timestamp
* @param $changeFreq string The change frequenty of the page, Valid values are "always", "hourly", "daily", "weekly", "monthly", "yearly" and "never".
* @param $priorty float The priority of the page, between 0.0 and 1.0
* @see AddElement
* @return string The URL node
*/
function AddUrl($loc, $lastMod = 0, $changeFreq = "monthly", $priority = 0.5) {
$page = new GoogleSitemapGeneratorPage($loc, $priority, $changeFreq, $lastMod);
$this->AddElement($page);
}
/**
* Adds an element to the sitemap
*
* @since 3.0
* @access private
* @author Arne Brachhold
* @param $page The element
*/
function AddElement(&$page) {
if(empty($page)) return;
$s = $page->Render();
if($this->_fileZipHandle && $this->IsGzipEnabled()) {
gzwrite($this->_fileZipHandle,$s);
}
if($this->_fileHandle) {
fwrite($this->_fileHandle,$s);
}
}
/**
* Checks if a file is writable and tries to make it if not.
*
* @since 3.05b
* @access private
* @author VJTD3
* @return bool true if writable
*/
function IsFileWritable($filename) {
//can we write?
if(!is_writable($filename)) {
//no we can't.
if(!@chmod($filename, 0666)) {
$pathtofilename = dirname($filename);
//Lets check if parent directory is writable.
if(!is_writable($pathtofilename)) {
//it's not writeable too.
if(!@chmod($pathtoffilename, 0666)) {
//darn couldn't fix up parrent directory this hosting is foobar.
//Lets error because of the permissions problems.
return false;
}
}
}
}
//we can write, return 1/true/happy dance.
return true;
}
/**
* Builds the sitemap and writes it into a xml file.
*
* ATTENTION PLUGIN DEVELOPERS! DONT CALL THIS METHOD DIRECTLY!
* The method is probably not available, since it is only loaded when needed.
* Use do_action("sm_rebuild"); if you want to rebuild the sitemap.
* Please refer to the documentation.txt for more details.
*
* @since 3.0
* @access public
* @author Arne Brachhold
* @return array An array with messages such as failed writes etc.
*/
function BuildSitemap() {
echo 'Generic PHP Sitemap Generator
';
//TODO - set a pingurl -> location of sitemap file *.gz if using*
$pingUrl = "http://http/domain/to/xyzsitemap.xml.gz";
//TODO - set full path to file location
$fileName = '/foo/bar/full/path/to/xyzsitemap.xml';
echo ("
Generating file: ". $fileName);
//check if file is there
if($this->IsFileWritable($fileName)) {
$this->_fileHandle = fopen($fileName,"w");
if(!$this->_fileHandle) echo "
ERROR: xml Not openable\n";
} else echo "
ERROR: xml file not writable\n";
//Write gzipped sitemap file
if($this->IsGzipEnabled()) {
$gzfileName = $fileName . '.gz';
if($this->IsFileWritable($gzfileName)) {
$this->_fileZipHandle = gzopen($gzfileName,"w1");
if(!$this->_fileZipHandle) echo "
ERROR: gzip Not openable\n";
} else echo "
ERROR: gzip not writable\n";
}
if(!$this->_fileHandle && !$this->_fileZipHandle) {
echo "
ERROR: ending - no filehandle\n";
return;
}
//BEGIN SITEMAP
//Content of the XML file
$this->AddElement(new GoogleSitemapGeneratorXmlEntry(''));
$this->AddElement(new GoogleSitemapGeneratorDebugEntry("generator=\"etiviti\""));
$this->AddElement(new GoogleSitemapGeneratorDebugEntry("sitemap-generator-url=\"http://etiviti.com\" sitemap-generator-version=\"1.0\""));
//TODO - add your generation timestamp
$this->AddElement(new GoogleSitemapGeneratorDebugEntry("generated-on=\"\""));
$this->AddElement(new GoogleSitemapGeneratorXmlEntry(''));
//SITEMAP MEAT AND POTATOES - db calls, loops, etc to actually generate sitemap url data goes here.
$this->AddUrl("http://foo/bar/html/page/", 'htmldatetimestamp', 'daily', '0.7');
//SITEMAP MEAT AND POTATOES
//CLOSE SITEMAP
$this->AddElement(new GoogleSitemapGeneratorXmlEntry(""));
if($this->_fileHandle && fclose($this->_fileHandle)) {
$this->_fileHandle = null;
} else echo "
ERROR: xml Could not close the sitemap file.";
if($this->IsGzipEnabled()) {
if($this->_fileZipHandle && fclose($this->_fileZipHandle)) {
$this->_fileZipHandle = null;
} else echo "
ERROR: gzip Could not close the zipped sitemap file";
}
//SEND PINGS
echo 'PINGS
';
//Ping Google
$sPingUrl="http://www.google.com/webmasters/sitemaps/ping?sitemap=" . urlencode($pingUrl);
echo '
PING: google: ' . $sPingUrl;
$pingres=$this->RemoteOpen($sPingUrl);
if($pingres==NULL || $pingres===false) {
echo '
PING: google' . $this->_lastError;
trigger_error("Failed to ping Google: " . htmlspecialchars(strip_tags($pingres)),E_USER_NOTICE);
} else {
echo '
PING: google - end';
}
//Ping Ask.com
$sPingUrl="http://submissions.ask.com/ping?sitemap=" . urlencode($pingUrl);
echo '
PING: ask: ' . $sPingUrl;
$pingres=$this->RemoteOpen($sPingUrl);
if($pingres==NULL || $pingres===false || strpos($pingres,"successfully received and added")===false) { //Ask.com returns 200 OK even if there was an error, so we need to check the content.
echo 'pinging ask' . $this->_lastError;
trigger_error("Failed to ping Ask.com: " . htmlspecialchars(strip_tags($pingres)),E_USER_NOTICE);
} else {
echo '
PING: pinging ask - end';
}
if ($this->_appid != null) {
//Ping YAHOO
$sPingUrl="http://search.yahooapis.com/SiteExplorerService/V1/updateNotification?appid=". $this->_appid ."&url=" . urlencode($pingUrl);
echo '
PING: yahoo: ' . $sPingUrl;
$pingres=$this->RemoteOpen($sPingUrl);
if($pingres==NULL || $pingres===false || strpos(strtolower($pingres),"success")===false) {
trigger_error("Failed to ping YAHOO: " . htmlspecialchars(strip_tags($pingres)),E_USER_NOTICE);
echo '
PING: yahoo: ' . $this->_lastError;
} else {
echo '
PING: yahoo - end';
}
}
//Ping Bing
$sPingUrl="http://www.bing.com/webmaster/ping.aspx?siteMap=" . urlencode($pingUrl);
echo '
PING: bing' . $sPingUrl;
$pingres=$this->RemoteOpen($sPingUrl);
if($pingres==NULL || $pingres===false || strpos($pingres,"Thanks for submitting your sitemap")===false) {
trigger_error("Failed to ping Bing: " . htmlspecialchars(strip_tags($pingres)),E_USER_NOTICE);
echo '
PING: bing' . $this->_lastError;
} else {
echo '
PING: bing - end';
}
echo '
generating sitemap complete';
//done...
return true;
}
/**
* Opens a remote file using Snoopy
* @since 3.0
* @param $url The URL to open
* @param $method get or post
* @param $postData An array with key=>value paris
* @param $timeout Timeout for the request, by default 10
* @return mixed False on error, the body of the response on success
*/
function RemoteOpen($url,$method = 'get', $postData = null, $timeout = 10) {
$s = new Snoopy();
$s->read_timeout = $timeout;
if($method == 'get') {
$s->fetch($url);
} else {
$s->submit($url,$postData);
}
if($s->status != "200") {
trigger_error('Snoopy Web Request failed: Status: ' . $s->status . "; Content: " . htmlspecialchars($s->results),E_USER_NOTICE);
}
return $s->results;
}
/**
* Converts a mysql datetime value into a unix timestamp
*
* @param The value in the mysql datetime format
* @return int The time in seconds
*/
function GetTimestampFromMySql($mysqlDateTime) {
list($date, $hours) = split(' ', $mysqlDateTime);
list($year,$month,$day) = split('-',$date);
list($hour,$min,$sec) = split(':',$hours);
return mktime(intval($hour), intval($min), intval($sec), intval($month), intval($day), intval($year));
}
}