API register_routes() for registering custom paths.

This replaces the existing updateItems() + extension hook in favour of consistency with the register_dataobject() interface.

Note that this will likely be superseded by something to do with the Config API in the future.
This commit is contained in:
Will Rossiter 2013-01-18 10:49:32 +13:00
parent 747059b6b7
commit 1c5e737d06
3 changed files with 153 additions and 3 deletions

View File

@ -29,13 +29,21 @@
class GoogleSitemap {
/**
* List of DataObject class names to include. As well as the change
* List of {@link DataObject} class names to include. As well as the change
* frequency and priority of each class.
*
* @var array
*/
private static $dataobjects = array();
/**
* List of custom routes to include in the sitemap (such as controller
* subclasses) as well as the change frequency and priority.
*
* @var array
*/
private static $routes = array();
/**
* Decorates the given DataObject with {@link GoogleSitemapDecorator}
* and pushes the class name to the registered DataObjects.
@ -61,6 +69,25 @@ class GoogleSitemap {
}
}
/**
* Registers multiple dataobjects in a single line. See {@link register_dataobject}
* for the heavy lifting
*
* @param array $dataobjects array of class names of DataObject to register
* @param string $changeFreq how often is this DataObject updated?
* Possible values:
* always, hourly, daily, weekly, monthly, yearly, never
* @param string $priority How important is this DataObject in comparison to other urls?
* Possible values: 0.1, 0.2 ... , 0.9, 1.0
*
* @return void
*/
public static function register_dataobjects($dataobjects, $changeFreq = 'monthly', $priority = '0.6') {
foreach($dataobjects as $obj) {
self::register_dataobject($obj, $changeFreq, $priority);
}
}
/**
* Checks whether the given class name is already registered or not.
*
@ -83,11 +110,56 @@ class GoogleSitemap {
/**
* Clears registered {@link DataObjects}. Useful for unit tests.
*
* @return void
*/
public static function clear_registered_dataobjects() {
self::$dataobjects = array();
}
/**
* Register a given route to the sitemap list
*
* @param string
* @param string
* @param string
*
* @return void
*/
public static function register_route($route, $changeFreq = 'monthly', $priority = '0.6') {
self::$routes = array_merge(self::$routes, array(
$route => array(
'frequency' => ($changeFreq) ? $changeFreq : 'monthly',
'priority' => ($priority) ? $priority : '0.6'
)
));
}
/**
* Registers a given list of relative urls. Will be merged with the current
* registered routes. If you want to replace them, please call {@link clear_routes}
*
* @param array
* @param string
* @param string
*
* @return void
*/
public static function register_routes($routes, $changeFreq = 'monthly', $priority = '0.6') {
foreach($routes as $route) {
self::register_route($route, $changeFreq, $priority);
}
}
/**
* Clears registered routes
*
* @return void
*/
public static function clear_registered_routes() {
self::$routes = array();
}
/**
* Constructs the list of data to include in the rendered sitemap. Links
* can include pages from the website, dataobjects (such as forum posts)
@ -107,6 +179,22 @@ class GoogleSitemap {
$filter = ($filter) ? "\"ShowInSearch\" = 1" : "";
$instances = Versioned::get_by_stage('SiteTree', 'Live', $filter);
}
else if($class == "GoogleSitemapRoute") {
$instances = array_slice(self::$routes, ($page - 1) * $count, $count);
$output = new ArrayList();
if($instances) {
foreach($instances as $route => $config) {
$output->push(new ArrayData(array(
'AbsoluteLink' => Director::absoluteURL($route),
'ChangeFrequency' => $config['frequency'],
'GooglePriority' => $config['priority']
)));
}
}
return $output;
}
else {
$instances = new DataList($class);
}
@ -196,7 +284,7 @@ class GoogleSitemap {
}
}
if(self::$dataobjects) {
if(count(self::$dataobjects) > 0) {
foreach(self::$dataobjects as $class => $config) {
$list = new DataList($class);
$list = $list->sort('LastEdited ASC');
@ -220,6 +308,17 @@ class GoogleSitemap {
}
}
if(count(self::$routes) > 0) {
$needed = ceil(count(self::$routes) / $countPerFile);
for($i = 1; $i <= $needed; $i++) {
$sitemaps->push(new ArrayData(array(
'ClassName' => 'GoogleSitemapRoute',
'Page' => $i
)));
}
}
return $sitemaps;
}

View File

@ -103,4 +103,17 @@ instead of the previous code you would write:
See the following blog post for more information:
http://www.silvercart.org/blog/dataobjects-and-googlesitemaps/
http://www.silvercart.org/blog/dataobjects-and-googlesitemaps/
### Including custom routes
Occasionally you may have a need to include custom url's in your sitemap for
your Controllers and other pages which don't exist in the database. To update
the sitemap to include those links call register_routes() with your array of
urls to include.
GoogleSitemap::register_routes(array(
'/my-custom-controller/',
'/Security/',
'/Security/login/'
));

View File

@ -22,12 +22,24 @@ class GoogleSitemapTest extends FunctionalTest {
}
GoogleSitemap::clear_registered_dataobjects();
GoogleSitemap::clear_registered_routes();
}
public function tearDown() {
parent::tearDown();
GoogleSitemap::clear_registered_dataobjects();
GoogleSitemap::clear_registered_routes();
}
public function testIndexFileWithCustomRoute() {
GoogleSitemap::register_route('/test/');
$response = $this->get('sitemap.xml');
$body = $response->getBody();
$expected = "<loc>". Director::absoluteURL("sitemap.xml/sitemap/GoogleSitemapRoute/1") ."</loc>";
$this->assertEquals(1, substr_count($body, $expected) , 'A link to the custom routes exists');
}
@ -49,6 +61,17 @@ class GoogleSitemapTest extends FunctionalTest {
$this->assertEquals(0, GoogleSitemap::get_items('GoogleSitemapTest_UnviewableDataObject', 1)->count());
}
public function testGetItemsWithCustomRoutes() {
GoogleSitemap::register_routes(array(
'/test-route/',
'/someother-route/',
'/fake-sitemap-route/'
));
$items = GoogleSitemap::get_items('GoogleSitemapRoute', 1);
$this->assertEquals(3, $items->count());
}
public function testAccessingSitemapRootXMLFile() {
GoogleSitemap::register_dataobject("GoogleSitemapTest_DataObject");
GoogleSitemap::register_dataobject("GoogleSitemapTest_OtherDataObject");
@ -98,6 +121,21 @@ class GoogleSitemapTest extends FunctionalTest {
Config::inst()->update('GoogleSitemap', 'objects_per_sitemap', $original);
}
public function testRegisterRoutesIncludesAllRoutes() {
GoogleSitemap::register_route('/test/');
GoogleSitemap::register_routes(array(
'/test/', // duplication should be replaced
'/unittests/',
'/anotherlink/'
), 'weekly');
$response = $this->get('sitemap.xml/sitemap/GoogleSitemapRoute/1');
$body = $response->getBody();
$this->assertEquals(200, $response->getStatusCode(), 'successful loaded nested sitemap');
$this->assertEquals(3, substr_count($body, "<loc>"));
}
public function testAccessingNestedSiteMap() {
$original = Config::inst()->get('GoogleSitemap', 'objects_per_sitemap');
Config::inst()->update('GoogleSitemap', 'objects_per_sitemap', 1);