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
|
||||
|
||||
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
|
||||
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
|
||||
|
||||
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.
|
||||
## Usage Overview
|
||||
|
||||
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();
|
||||
|
||||
See docs/en/* for more information about configuring the module.
|
||||
|
||||
|
10
_config.php
10
_config.php
@ -5,6 +5,10 @@ Director::addRules(10, array(
|
||||
'sitemap.xml' => 'GoogleSitemap',
|
||||
));
|
||||
|
||||
// add the extension
|
||||
Object::add_extension('SiteTree', 'GoogleSitemapDecorator');
|
||||
?>
|
||||
// add the extension to pages
|
||||
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
|
||||
|
||||
/**
|
||||
* Initial implementation of Sitemap support.
|
||||
* GoogleSitemap should handle requests to 'sitemap.xml'
|
||||
@ -11,6 +10,7 @@
|
||||
* sitemap whenever the GoogleBot visits your website.
|
||||
*
|
||||
* Enabling notification of Google after every publish (in your _config.php):
|
||||
*
|
||||
* <example>
|
||||
* GoogleSitemap::enable_google_notificaton();
|
||||
* </example>
|
||||
@ -19,7 +19,6 @@
|
||||
*
|
||||
* @package googlesitemaps
|
||||
*/
|
||||
|
||||
class GoogleSitemap extends Controller {
|
||||
|
||||
/**
|
||||
@ -41,60 +40,166 @@ class GoogleSitemap extends Controller {
|
||||
* @var boolean
|
||||
*/
|
||||
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() {
|
||||
$filter = '';
|
||||
|
||||
|
||||
$bt = defined('DB::USE_ANSI_SQL') ? "\"" : "`";
|
||||
|
||||
if(self::$use_show_in_search) {
|
||||
$filter = "{$bt}ShowInSearch{$bt} = 1";
|
||||
}
|
||||
|
||||
|
||||
$this->Pages = Versioned::get_by_stage('SiteTree', 'Live', $filter);
|
||||
|
||||
$newPages = new DataObjectSet();
|
||||
|
||||
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)) {
|
||||
// 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.
|
||||
$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)) {
|
||||
|
||||
$created = $page->dbObject('Created');
|
||||
// The one field that isn't easy to deal with in the template is
|
||||
// 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->value = date('Y-m-d H:i:s');
|
||||
$versions = $page->Version;
|
||||
$now->value = $date;
|
||||
$versions = (isset($prop['Version'])) ? $prop['Version'] : 1;
|
||||
|
||||
$timediff = $now->format('U') - $created->format('U');
|
||||
|
||||
|
||||
// Check how many revisions have been made over the lifetime of the
|
||||
// Page for a rough estimate of it's changing frequency.
|
||||
|
||||
$period = $timediff / ($versions + 1);
|
||||
|
||||
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';
|
||||
|
||||
if($period > 60*60*24*365) {
|
||||
// > 1 year
|
||||
$page->ChangeFreq = 'yearly';
|
||||
}
|
||||
elseif($period > 60*60*24*30) {
|
||||
$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';
|
||||
}
|
||||
|
||||
|
||||
$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())
|
||||
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",
|
||||
"sitemap=" . $location);
|
||||
$response = HTTP::sendRequest(
|
||||
"www.google.com",
|
||||
"/webmasters/sitemaps/ping",
|
||||
sprintf("sitemap=%s", $location)
|
||||
);
|
||||
|
||||
return $response;
|
||||
}
|
||||
|
||||
/**
|
||||
* Enable pings to google.com whenever sitemap changes.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public static function enable_google_notification() {
|
||||
self::$google_notification_enabled = true;
|
||||
@ -132,11 +245,16 @@ class GoogleSitemap extends Controller {
|
||||
|
||||
/**
|
||||
* Disables pings to google when the sitemap changes.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public static function disable_google_notification() {
|
||||
self::$google_notification_enabled = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Default controller handler for the sitemap.xml file
|
||||
*/
|
||||
function index($url) {
|
||||
if(self::$enabled) {
|
||||
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() {
|
||||
self::$enabled = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Disable the sitemap.xml file
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public static function disable() {
|
||||
self::$enabled = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -6,7 +6,16 @@
|
||||
*
|
||||
* @package googlesitemaps
|
||||
*/
|
||||
class GoogleSitemapDecorator extends SiteTreeDecorator {
|
||||
class GoogleSitemapDecorator extends DataObjectDecorator {
|
||||
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @package googlesitemaps
|
||||
*/
|
||||
|
||||
class GoogleSitemapSiteTreeDecorator extends SiteTreeDecorator {
|
||||
|
||||
function extraStatics() {
|
||||
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