2008-11-19 00:10:33 +01:00
< ? php
/**
* Initial implementation of Sitemap support .
* GoogleSitemap should handle requests to 'sitemap.xml'
* the other two classes are used to render the sitemap .
*
* You can notify ( " ping " ) Google about a changed sitemap
* automatically whenever a new page is published or unpublished .
* By default , Google is not notified , and will pick up your new
* sitemap whenever the GoogleBot visits your website .
*
* Enabling notification of Google after every publish ( in your _config . php ) :
* < example
* GoogleSitemap :: enable_google_notificaton ();
* </ example >
*
* @ see http :// www . google . com / support / webmasters / bin / answer . py ? hl = en & answer = 34609
*
2009-08-12 05:55:21 +02:00
* @ package googlesitemaps
2008-11-19 00:10:33 +01:00
*/
class GoogleSitemap extends Controller {
/**
* @ var boolean
*/
protected static $enabled = true ;
/**
* @ var DataObjectSet
*/
protected $Pages ;
/**
* @ var boolean
*/
protected static $google_notification_enabled = false ;
2009-08-12 09:44:32 +02:00
/**
* @ var boolean
*/
protected static $use_show_in_search = true ;
2008-11-19 00:10:33 +01:00
public function Items () {
2009-08-12 09:44:32 +02:00
$filter = '' ;
if ( self :: $use_show_in_search ) {
$filter = '`ShowInSearch` = 1' ;
}
$this -> Pages = Versioned :: get_by_stage ( 'SiteTree' , 'Live' , $filter );
2008-11-19 00:10:33 +01:00
$newPages = new DataObjectSet ();
2009-08-12 09:44:32 +02:00
if ( $this -> Pages ) {
foreach ( $this -> Pages as $page ) {
// Only include pages from this host and pages which are not an instance of ErrorPage
// We prefix $_SERVER['HTTP_HOST'] with 'http://' so that parse_url to help parse_url identify the host name component; we could use another protocol (like
// 'ftp://' as the prefix and the code would work the same.
if ( parse_url ( $page -> AbsoluteLink (), PHP_URL_HOST ) == parse_url ( 'http://' . $_SERVER [ 'HTTP_HOST' ], PHP_URL_HOST ) && ! ( $page instanceof ErrorPage )) {
// If the page has been set to 0 priority, we set a flag so it won't be included
if ( $page -> canView () && ( ! isset ( $page -> Priority ) || $page -> Priority > 0 )) {
// The one field that isn't easy to deal with in the template is
// Change frequency, so we set that here.
$properties = $page -> toMap ();
2009-11-14 02:17:29 +01:00
$created = new SS_Datetime ();
2009-08-12 09:44:32 +02:00
$created -> value = $properties [ 'Created' ];
2009-11-14 02:17:29 +01:00
$now = new SS_Datetime ();
2009-08-12 09:44:32 +02:00
$now -> value = date ( 'Y-m-d H:i:s' );
$versions = $properties [ 'Version' ];
$timediff = $now -> format ( 'U' ) - $created -> format ( 'U' );
2008-11-19 00:10:33 +01:00
2009-08-12 09:44:32 +02:00
// Check how many revisions have been made over the lifetime of the
// Page for a rough estimate of it's changing frequency.
2008-11-19 00:10:33 +01:00
2009-08-12 09:44:32 +02:00
$period = $timediff / ( $versions + 1 );
2008-11-19 00:10:33 +01:00
2009-08-12 09:44:32 +02:00
if ( $period > 60 * 60 * 24 * 365 ) { // > 1 year
$page -> ChangeFreq = 'yearly' ;
} elseif ( $period > 60 * 60 * 24 * 30 ) { // > ~1 month
$page -> ChangeFreq = 'monthly' ;
} elseif ( $period > 60 * 60 * 24 * 7 ) { // > 1 week
$page -> ChangeFreq = 'weekly' ;
} elseif ( $period > 60 * 60 * 24 ) { // > 1 day
$page -> ChangeFreq = 'daily' ;
} elseif ( $period > 60 * 60 ) { // > 1 hour
$page -> ChangeFreq = 'hourly' ;
} else { // < 1 hour
$page -> ChangeFreq = 'always' ;
}
2008-11-19 00:10:33 +01:00
2009-08-12 09:44:32 +02:00
$newPages -> push ( $page );
}
2008-11-19 00:10:33 +01:00
}
}
2009-08-12 09:44:32 +02:00
return $newPages ;
2008-11-19 00:10:33 +01:00
}
}
/**
* Notifies Google about changes to your sitemap .
* Triggered automatically on every publish / unpublish of a page .
* This behaviour is disabled by default , enable with :
* GoogleSitemap :: enable_google_notificaton ();
*
* If the site is in " dev-mode " , no ping will be sent regardless wether
* the Google notification is enabled .
*
* @ return string Response text
*/
static function ping () {
if ( ! self :: $enabled ) return false ;
//Don't ping if the site has disabled it, or if the site is in dev mode
if ( ! GoogleSitemap :: $google_notification_enabled || Director :: isDev ())
return ;
$location = urlencode ( Director :: absoluteBaseURL () . '/sitemap.xml' );
$response = HTTP :: sendRequest ( " www.google.com " , " /webmasters/sitemaps/ping " ,
" sitemap= " . $location );
return $response ;
}
/**
* Enable pings to google . com whenever sitemap changes .
*/
public static function enable_google_notification () {
self :: $google_notification_enabled = true ;
}
/**
* Disables pings to google when the sitemap changes .
*/
public static function disable_google_notification () {
self :: $google_notification_enabled = false ;
}
function index ( $url ) {
if ( self :: $enabled ) {
2008-12-05 03:47:07 +01:00
SSViewer :: set_source_file_comments ( false );
2008-11-19 00:10:33 +01:00
// We need to override the default content-type
ContentNegotiator :: disable ();
2009-04-27 01:03:56 +02:00
$this -> getResponse () -> addHeader ( 'Content-Type' , 'application/xml; charset="utf-8"' );
2008-11-19 00:10:33 +01:00
// But we want to still render.
return array ();
} else {
return new HTTPResponse ( 'Not allowed' , 405 );
}
}
public static function enable () {
self :: $enabled = true ;
}
public static function disable () {
self :: $enabled = false ;
}
2009-08-12 05:51:43 +02:00
}