mirror of
https://github.com/wilr/silverstripe-googlesitemaps.git
synced 2024-10-22 11:05:48 +02:00
FEATURE: added ability to add google sitemap indexes for dataobjects. Added documentation and.
APICHANGE: moved GoogleSiteMapDecorator to GoogleSitemapSiteTreeDecorator to use the original for a hook for extending on googlesitemaps on dataobjects only.
This commit is contained in:
parent
c62538a860
commit
9c0d50e726
20
README.md
20
README.md
@ -11,7 +11,7 @@
|
|||||||
## Documentation
|
## Documentation
|
||||||
|
|
||||||
SilverStripe provides support for the Google Sitemaps XML system, enabling
|
SilverStripe provides support for the Google Sitemaps XML system, enabling
|
||||||
Google and other search engines to see all pages on your site. This helps
|
Google and other search engines to see all urls on your site. This helps
|
||||||
your SilverStripe website rank well in search engines, and to encourage the
|
your SilverStripe website rank well in search engines, and to encourage the
|
||||||
information on your site to be discovered by Google quickly.
|
information on your site to be discovered by Google quickly.
|
||||||
|
|
||||||
@ -20,21 +20,7 @@ be visited: http://yoursite.com/sitemap.xml
|
|||||||
|
|
||||||
See http://en.wikipedia.org/wiki/Sitemaps for info on this format
|
See http://en.wikipedia.org/wiki/Sitemaps for info on this format
|
||||||
|
|
||||||
In addition, whenever you publish a new or republish an existing page,
|
## Usage Overview
|
||||||
SilverStripe automatically informs Google of the change, encouraging a Google
|
|
||||||
to take notice. If you install the SilverStripe Google Analytics module, you
|
|
||||||
can see if Google has updated your page as a result.
|
|
||||||
|
|
||||||
By default, SilverStripe informs Google that the importance of a page depends
|
See docs/en/* for more information about configuring the module.
|
||||||
on its position of in the sitemap. "Top level" pages are most important, and
|
|
||||||
the deeper a page is nested, the less important it is. (For each level,
|
|
||||||
Importance drops from 1.0, to 0.9, to 0.8, and so on, until 0.1 is reached).
|
|
||||||
|
|
||||||
In the CMS, in the "Content/GoogleSitemap" tab, you can set the page importance
|
|
||||||
manually, including requesting to have the page excluded from the google sitemap.
|
|
||||||
|
|
||||||
### Setup automatic pinging
|
|
||||||
|
|
||||||
GoogleSitemap::enable_google_notificaton();
|
|
||||||
|
|
||||||
|
|
||||||
|
10
_config.php
10
_config.php
@ -5,6 +5,10 @@ Director::addRules(10, array(
|
|||||||
'sitemap.xml' => 'GoogleSitemap',
|
'sitemap.xml' => 'GoogleSitemap',
|
||||||
));
|
));
|
||||||
|
|
||||||
// add the extension
|
// add the extension to pages
|
||||||
Object::add_extension('SiteTree', 'GoogleSitemapDecorator');
|
Object::add_extension('SiteTree', 'GoogleSitemapSiteTreeDecorator');
|
||||||
?>
|
|
||||||
|
// if you need to add this to DataObjects include the following in
|
||||||
|
// your own _config:
|
||||||
|
|
||||||
|
// GoogleSiteMap::register_dataobject('MyDataObject');
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initial implementation of Sitemap support.
|
* Initial implementation of Sitemap support.
|
||||||
* GoogleSitemap should handle requests to 'sitemap.xml'
|
* GoogleSitemap should handle requests to 'sitemap.xml'
|
||||||
@ -11,6 +10,7 @@
|
|||||||
* sitemap whenever the GoogleBot visits your website.
|
* sitemap whenever the GoogleBot visits your website.
|
||||||
*
|
*
|
||||||
* Enabling notification of Google after every publish (in your _config.php):
|
* Enabling notification of Google after every publish (in your _config.php):
|
||||||
|
*
|
||||||
* <example>
|
* <example>
|
||||||
* GoogleSitemap::enable_google_notificaton();
|
* GoogleSitemap::enable_google_notificaton();
|
||||||
* </example>
|
* </example>
|
||||||
@ -19,7 +19,6 @@
|
|||||||
*
|
*
|
||||||
* @package googlesitemaps
|
* @package googlesitemaps
|
||||||
*/
|
*/
|
||||||
|
|
||||||
class GoogleSitemap extends Controller {
|
class GoogleSitemap extends Controller {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -41,60 +40,166 @@ class GoogleSitemap extends Controller {
|
|||||||
* @var boolean
|
* @var boolean
|
||||||
*/
|
*/
|
||||||
protected static $use_show_in_search = true;
|
protected static $use_show_in_search = true;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* List of DataObjects to show in sitemap.xml
|
||||||
|
*
|
||||||
|
* @var array
|
||||||
|
*/
|
||||||
|
public static $google_sitemap_dataobjects = array();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* List of DataObjects change frequency
|
||||||
|
*
|
||||||
|
* @var array
|
||||||
|
*/
|
||||||
|
public static $google_sitemap_dataobjects_changefreq = array();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Decorates the given DataObject with {@link GoogleSitemapDecorator}
|
||||||
|
* and pushes the class name to the registered DataObjects.
|
||||||
|
* Note that all registered DataObjects need the method AbsoluteLink().
|
||||||
|
*
|
||||||
|
* @param string $className name of DataObject to register
|
||||||
|
* @param string $changeFreq
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public static function register_dataobject($className, $changeFreq = 'monthly') {
|
||||||
|
if (!self::is_registered($className)) {
|
||||||
|
Object::add_extension($className, 'GoogleSitemapDecorator');
|
||||||
|
self::$google_sitemap_dataobjects[] = $className;
|
||||||
|
self::$google_sitemap_dataobjects_changefreq[] = $changeFreq;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks whether the given class name is already registered or not.
|
||||||
|
*
|
||||||
|
* @param string $className Name of DataObject to check
|
||||||
|
*
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public static function is_registered($className) {
|
||||||
|
return in_array($className, self::$google_sitemap_dataobjects);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds DataObjects to the existing DataObjectSet with pages from the
|
||||||
|
* site tree
|
||||||
|
*
|
||||||
|
* @param DataObjectSet $newPages
|
||||||
|
*
|
||||||
|
* @return DataObjectSet
|
||||||
|
*/
|
||||||
|
protected function addRegisteredDataObjects() {
|
||||||
|
$output = new DataObjectSet();
|
||||||
|
|
||||||
|
foreach(self::$google_sitemap_dataobjects as $index => $className) {
|
||||||
|
$dataObjectSet = DataObject::get($className);
|
||||||
|
|
||||||
|
if($dataObjectSet) {
|
||||||
|
foreach($dataObjectSet as $dataObject) {
|
||||||
|
if($dataObject->canView() && (!isset($dataObject->Priority) || $dataObject->Priority > 0)) {
|
||||||
|
$dataObject->ChangeFreq = self::$google_sitemap_dataobjects_changefreq[$index];
|
||||||
|
|
||||||
|
if(!isset($dataObject->Priority)) {
|
||||||
|
$dataObject->Priority = 1.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
$output->push($dataObject);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $output;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns all the links to {@link SiteTree} pages and
|
||||||
|
* {@link DataObject} urls on the page
|
||||||
|
*
|
||||||
|
* @return DataObjectSet
|
||||||
|
*/
|
||||||
public function Items() {
|
public function Items() {
|
||||||
$filter = '';
|
$filter = '';
|
||||||
|
|
||||||
$bt = defined('DB::USE_ANSI_SQL') ? "\"" : "`";
|
$bt = defined('DB::USE_ANSI_SQL') ? "\"" : "`";
|
||||||
|
|
||||||
if(self::$use_show_in_search) {
|
if(self::$use_show_in_search) {
|
||||||
$filter = "{$bt}ShowInSearch{$bt} = 1";
|
$filter = "{$bt}ShowInSearch{$bt} = 1";
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->Pages = Versioned::get_by_stage('SiteTree', 'Live', $filter);
|
$this->Pages = Versioned::get_by_stage('SiteTree', 'Live', $filter);
|
||||||
|
|
||||||
$newPages = new DataObjectSet();
|
$newPages = new DataObjectSet();
|
||||||
|
|
||||||
if($this->Pages) {
|
if($this->Pages) {
|
||||||
foreach($this->Pages as $page) {
|
foreach($this->Pages as $page) {
|
||||||
// Only include pages from this host and pages which are not an instance of ErrorPage
|
// Only include pages from this host and pages which are not an
|
||||||
// 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
|
// instance of ErrorPage. We prefix $_SERVER['HTTP_HOST'] with
|
||||||
// 'ftp://' as the prefix and the code would work the same.
|
// 'http://' so that parse_url to help parse_url identify the
|
||||||
if(parse_url($page->AbsoluteLink(), PHP_URL_HOST) == parse_url('http://' . $_SERVER['HTTP_HOST'], PHP_URL_HOST) && !($page instanceof ErrorPage)) {
|
// host name component; we could use another protocol (like ftp
|
||||||
|
// as the prefix and the code would work the same.
|
||||||
|
$pageHttp = parse_url($page->AbsoluteLink(), PHP_URL_HOST);
|
||||||
|
$hostHttp = parse_url('http://' . $_SERVER['HTTP_HOST'], PHP_URL_HOST);
|
||||||
|
|
||||||
|
if(($pageHttp == $hostHttp) && !($page instanceof ErrorPage)) {
|
||||||
|
|
||||||
// If the page has been set to 0 priority, we set a flag so it won't be included
|
// 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)) {
|
if($page->canView() && (!isset($page->Priority) || $page->Priority > 0)) {
|
||||||
|
// The one field that isn't easy to deal with in the template is
|
||||||
$created = $page->dbObject('Created');
|
// Change frequency, so we set that here.
|
||||||
|
$date = date('Y-m-d H:i:s');
|
||||||
|
|
||||||
|
$prop = $page->toMap();
|
||||||
|
$created = new SS_Datetime();
|
||||||
|
$created->value = (isset($prop['Created'])) ? $prop['Created'] : $date;
|
||||||
|
|
||||||
$now = new SS_Datetime();
|
$now = new SS_Datetime();
|
||||||
$now->value = date('Y-m-d H:i:s');
|
$now->value = $date;
|
||||||
$versions = $page->Version;
|
$versions = (isset($prop['Version'])) ? $prop['Version'] : 1;
|
||||||
|
|
||||||
$timediff = $now->format('U') - $created->format('U');
|
$timediff = $now->format('U') - $created->format('U');
|
||||||
|
|
||||||
// Check how many revisions have been made over the lifetime of the
|
// Check how many revisions have been made over the lifetime of the
|
||||||
// Page for a rough estimate of it's changing frequency.
|
// Page for a rough estimate of it's changing frequency.
|
||||||
|
|
||||||
$period = $timediff / ($versions + 1);
|
$period = $timediff / ($versions + 1);
|
||||||
|
|
||||||
if($period > 60*60*24*365) { // > 1 year
|
if($period > 60*60*24*365) {
|
||||||
$page->ChangeFreq='yearly';
|
// > 1 year
|
||||||
} elseif($period > 60*60*24*30) { // > ~1 month
|
$page->ChangeFreq = 'yearly';
|
||||||
$page->ChangeFreq='monthly';
|
}
|
||||||
} elseif($period > 60*60*24*7) { // > 1 week
|
elseif($period > 60*60*24*30) {
|
||||||
$page->ChangeFreq='weekly';
|
$page->ChangeFreq = 'monthly';
|
||||||
} elseif($period > 60*60*24) { // > 1 day
|
}
|
||||||
$page->ChangeFreq='daily';
|
elseif($period > 60*60*24*7) {
|
||||||
} elseif($period > 60*60) { // > 1 hour
|
// > 1 week
|
||||||
$page->ChangeFreq='hourly';
|
$page->ChangeFreq = 'weekly';
|
||||||
} else { // < 1 hour
|
}
|
||||||
$page->ChangeFreq='always';
|
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';
|
||||||
}
|
}
|
||||||
|
|
||||||
$newPages->push($page);
|
$newPages->push($page);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return $newPages;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$newPages->merge($this->addRegisteredDataObjects());
|
||||||
|
|
||||||
|
return $newPages;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -115,16 +220,24 @@ class GoogleSitemap extends Controller {
|
|||||||
if(!GoogleSitemap::$google_notification_enabled || Director::isDev())
|
if(!GoogleSitemap::$google_notification_enabled || Director::isDev())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
$location = urlencode(Director::absoluteBaseURL() . '/sitemap.xml');
|
$location = urlencode(Controller::join_links(
|
||||||
|
Director::absoluteBaseURL(),
|
||||||
|
'sitemap.xml'
|
||||||
|
));
|
||||||
|
|
||||||
$response = HTTP::sendRequest("www.google.com", "/webmasters/sitemaps/ping",
|
$response = HTTP::sendRequest(
|
||||||
"sitemap=" . $location);
|
"www.google.com",
|
||||||
|
"/webmasters/sitemaps/ping",
|
||||||
|
sprintf("sitemap=%s", $location)
|
||||||
|
);
|
||||||
|
|
||||||
return $response;
|
return $response;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Enable pings to google.com whenever sitemap changes.
|
* Enable pings to google.com whenever sitemap changes.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
*/
|
*/
|
||||||
public static function enable_google_notification() {
|
public static function enable_google_notification() {
|
||||||
self::$google_notification_enabled = true;
|
self::$google_notification_enabled = true;
|
||||||
@ -132,11 +245,16 @@ class GoogleSitemap extends Controller {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Disables pings to google when the sitemap changes.
|
* Disables pings to google when the sitemap changes.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
*/
|
*/
|
||||||
public static function disable_google_notification() {
|
public static function disable_google_notification() {
|
||||||
self::$google_notification_enabled = false;
|
self::$google_notification_enabled = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Default controller handler for the sitemap.xml file
|
||||||
|
*/
|
||||||
function index($url) {
|
function index($url) {
|
||||||
if(self::$enabled) {
|
if(self::$enabled) {
|
||||||
SSViewer::set_source_file_comments(false);
|
SSViewer::set_source_file_comments(false);
|
||||||
@ -149,11 +267,21 @@ class GoogleSitemap extends Controller {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Enable the sitemap.xml file
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
public static function enable() {
|
public static function enable() {
|
||||||
self::$enabled = true;
|
self::$enabled = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Disable the sitemap.xml file
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
public static function disable() {
|
public static function disable() {
|
||||||
self::$enabled = false;
|
self::$enabled = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -6,7 +6,16 @@
|
|||||||
*
|
*
|
||||||
* @package googlesitemaps
|
* @package googlesitemaps
|
||||||
*/
|
*/
|
||||||
class GoogleSitemapDecorator extends SiteTreeDecorator {
|
class GoogleSitemapDecorator extends DataObjectDecorator {
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @package googlesitemaps
|
||||||
|
*/
|
||||||
|
|
||||||
|
class GoogleSitemapSiteTreeDecorator extends SiteTreeDecorator {
|
||||||
|
|
||||||
function extraStatics() {
|
function extraStatics() {
|
||||||
return array(
|
return array(
|
||||||
|
0
docs/_manifest_exclude
Normal file
0
docs/_manifest_exclude
Normal file
84
docs/en/index.md
Normal file
84
docs/en/index.md
Normal file
@ -0,0 +1,84 @@
|
|||||||
|
# Google Sitemaps Module
|
||||||
|
|
||||||
|
SilverStripe provides support for the Google Sitemaps XML system, enabling
|
||||||
|
Google and other search engines to see all pages on your site. This helps
|
||||||
|
your SilverStripe website rank well in search engines, and to encourage the
|
||||||
|
information on your site to be discovered by Google quickly.
|
||||||
|
|
||||||
|
Therefore, all Silverstripe websites contain a special controller which can
|
||||||
|
be visited: http://yoursite.com/sitemap.xml
|
||||||
|
|
||||||
|
See http://en.wikipedia.org/wiki/Sitemaps for info on this format
|
||||||
|
|
||||||
|
In addition, whenever you publish a new or republish an existing page,
|
||||||
|
SilverStripe automatically informs Google of the change, encouraging a Google
|
||||||
|
to take notice. If you install the SilverStripe Google Analytics module, you
|
||||||
|
can see if Google has updated your page as a result.
|
||||||
|
|
||||||
|
By default, SilverStripe informs Google that the importance of a page depends
|
||||||
|
on its position of in the sitemap. "Top level" pages are most important, and
|
||||||
|
the deeper a page is nested, the less important it is. (For each level,
|
||||||
|
Importance drops from 1.0, to 0.9, to 0.8, and so on, until 0.1 is reached).
|
||||||
|
|
||||||
|
In the CMS, in the "Content/GoogleSitemap" tab, you can set the page importance
|
||||||
|
manually, including requesting to have the page excluded from the google sitemap.
|
||||||
|
|
||||||
|
|
||||||
|
## Setup automatic pinging
|
||||||
|
|
||||||
|
GoogleSitemap::enable_google_notificaton();
|
||||||
|
|
||||||
|
### Include Dataobjects in listing
|
||||||
|
|
||||||
|
The module provides support for including DataObject subclasses as pages in
|
||||||
|
the SiteTree such as comments, forum posts and other pages which are created
|
||||||
|
by DataObjects.
|
||||||
|
|
||||||
|
To include a DataObject in the Sitemap it requires that your subclass defines
|
||||||
|
two functions.
|
||||||
|
|
||||||
|
* AbsoluteLink() function which returns the URL for this DataObject
|
||||||
|
* canView() function which returns a boolean value.
|
||||||
|
|
||||||
|
The SilverStripe convention is to use a Link function to define the AbsoluteLink.
|
||||||
|
This enables $Link to work for relative links (while in templates) and $AbsoluteLink
|
||||||
|
to work for RSS Feeds and the Sitemap Links.
|
||||||
|
|
||||||
|
The following is a barebones example of a DataObject called 'MyDataObject'. It assumes
|
||||||
|
that you have a controller called 'MyController' which has a show method to show the
|
||||||
|
DataObject by it's ID.
|
||||||
|
|
||||||
|
<?php
|
||||||
|
|
||||||
|
class MyDataObject extends DataObject {
|
||||||
|
|
||||||
|
function canView() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
function AbsoluteLink() {
|
||||||
|
return Director::absoluteURL($this->Link());
|
||||||
|
}
|
||||||
|
|
||||||
|
function Link() {
|
||||||
|
return 'MyController/show/'. $this->ID;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
After those methods have been defined on your DataObject you now need to tell
|
||||||
|
googlesitemaps that it should be listed in the sitemap.xml file. Include the
|
||||||
|
following in your _config.php file.
|
||||||
|
|
||||||
|
GoogleSitemap::register_dataobject('MyDataObject');
|
||||||
|
|
||||||
|
If you need to change the frequency of the indexing, you can pass the change
|
||||||
|
frequency (daily, weekly, monthly) as a second parameter to register().
|
||||||
|
|
||||||
|
So instead of the previous code you would write:
|
||||||
|
|
||||||
|
GoogleSitemap::register('MyDataObject', 'daily');
|
||||||
|
|
||||||
|
See the following blog post for more information:
|
||||||
|
|
||||||
|
http://www.silvercart.org/blog/dataobjects-and-googlesitemaps/
|
Loading…
Reference in New Issue
Block a user