mirror of
https://github.com/wilr/silverstripe-googlesitemaps.git
synced 2024-10-22 11:05:48 +02:00
feat: implement Sitemapable (#181)
This commit is contained in:
parent
def6be347c
commit
8a7c8aa9cc
@ -6,13 +6,13 @@
|
|||||||
|
|
||||||
## Maintainer Contact
|
## Maintainer Contact
|
||||||
|
|
||||||
* Will Rossiter (Nickname: wrossiter, willr) <will@fullscreen.io>
|
- Will Rossiter (Nickname: wrossiter, willr) <will@fullscreen.io>
|
||||||
|
|
||||||
## Installation
|
## Installation
|
||||||
|
|
||||||
> composer require "wilr/silverstripe-googlesitemaps"
|
> composer require "wilr/silverstripe-googlesitemaps"
|
||||||
|
|
||||||
If you're using Silverstripe 5 then version 3 or `dev-main` will work.
|
If you're using Silverstripe 5 then version `3` or `dev-main` will work.
|
||||||
|
|
||||||
For Silverstripe 4 use the `2.x` branch line.
|
For Silverstripe 4 use the `2.x` branch line.
|
||||||
|
|
||||||
@ -34,4 +34,4 @@ See docs/en for more information about configuring the module.
|
|||||||
|
|
||||||
## Troubleshooting
|
## Troubleshooting
|
||||||
|
|
||||||
* Flush this route to ensure the changes take effect (e.g http://yoursite.com/sitemap.xml?flush=1)
|
- Flush this route to ensure the changes take effect (e.g http://yoursite.com/sitemap.xml?flush=1)
|
||||||
|
10
_config.php
Normal file
10
_config.php
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
use SilverStripe\Core\ClassInfo;
|
||||||
|
use Wilr\GoogleSitemaps\GoogleSitemap;
|
||||||
|
|
||||||
|
if (0 === strpos(ltrim($_SERVER['REQUEST_URI'], '/'), 'sitemap')) {
|
||||||
|
foreach (ClassInfo::implementorsOf(Sitemapable::class) as $className) {
|
||||||
|
GoogleSitemap::register_dataobject($className);
|
||||||
|
}
|
||||||
|
}
|
@ -35,10 +35,11 @@ config file `mysite/_config/googlesitemaps.yml` with the following outline:
|
|||||||
After: googlesitemaps
|
After: googlesitemaps
|
||||||
---
|
---
|
||||||
Wilr\GoogleSitemaps\GoogleSitemap:
|
Wilr\GoogleSitemaps\GoogleSitemap:
|
||||||
enabled: true
|
|
||||||
objects_per_sitemap: 1000
|
enabled: true
|
||||||
google_notification_enabled: false
|
objects_per_sitemap: 1000
|
||||||
use_show_in_search: true
|
google_notification_enabled: false
|
||||||
|
use_show_in_search: true
|
||||||
|
|
||||||
You can now alter any of those properties to set your needs. A popular option
|
You can now alter any of those properties to set your needs. A popular option
|
||||||
is to turn on automatic pinging so that Google is notified of any updates to
|
is to turn on automatic pinging so that Google is notified of any updates to
|
||||||
@ -50,22 +51,11 @@ editing the `google_notification_enabled` option to true
|
|||||||
After: googlesitemaps
|
After: googlesitemaps
|
||||||
---
|
---
|
||||||
Wilr\GoogleSitemaps\GoogleSitemap:
|
Wilr\GoogleSitemaps\GoogleSitemap:
|
||||||
enabled: true
|
|
||||||
objects_per_sitemap: 1000
|
|
||||||
google_notification_enabled: true
|
|
||||||
use_show_in_search: true
|
|
||||||
|
|
||||||
### Bing Ping Support
|
enabled: true
|
||||||
|
objects_per_sitemap: 1000
|
||||||
To ping Bing whenever your sitemap is updated, set `bing_notification_enabled`
|
google_notification_enabled: true
|
||||||
|
use_show_in_search: true
|
||||||
---
|
|
||||||
Name: customgooglesitemaps
|
|
||||||
After: googlesitemaps
|
|
||||||
---
|
|
||||||
Wilr\GoogleSitemaps\GoogleSitemap:
|
|
||||||
enabled: true
|
|
||||||
bing_notification_enabled: true
|
|
||||||
|
|
||||||
### Including DataObjects
|
### Including DataObjects
|
||||||
|
|
||||||
@ -76,8 +66,8 @@ database as DataObject subclasses.
|
|||||||
To include a DataObject instance in the Sitemap it requires that your subclass
|
To include a DataObject instance in the Sitemap it requires that your subclass
|
||||||
defines two functions:
|
defines two functions:
|
||||||
|
|
||||||
* AbsoluteLink() function which returns the URL for this DataObject
|
- AbsoluteLink() function which returns the URL for this DataObject
|
||||||
* canView() function which returns a boolean value.
|
- canView() function which returns a boolean value.
|
||||||
|
|
||||||
The following is a barebones example of a DataObject called 'MyDataObject'. It
|
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
|
assumes that you have a controller called 'MyController' which has a show method
|
||||||
@ -103,10 +93,9 @@ to show the DataObject by its ID.
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
After those methods have been defined on your DataObject you now need to tell
|
After those methods have been defined on your DataObject you now need to tell
|
||||||
the Google Sitemaps module that it should be listed in the sitemap.xml file. To
|
the Google Sitemaps module that it should be listed in the sitemap.xml file. To
|
||||||
do that, include the following in your _config.php file.
|
do that, include the following in your \_config.php file.
|
||||||
|
|
||||||
use Wilr\GoogleSitemaps\GoogleSitemap;
|
use Wilr\GoogleSitemaps\GoogleSitemap;
|
||||||
|
|
||||||
@ -138,3 +127,21 @@ urls to include.
|
|||||||
'/Security/',
|
'/Security/',
|
||||||
'/Security/login/'
|
'/Security/login/'
|
||||||
));
|
));
|
||||||
|
|
||||||
|
### Sitemapable
|
||||||
|
|
||||||
|
For automatic registration of a DataObject subclass, implement the `Sitemapable`
|
||||||
|
extension
|
||||||
|
|
||||||
|
```
|
||||||
|
<?php
|
||||||
|
|
||||||
|
|
||||||
|
class MyDataObject extends DataObject implements Sitemapable
|
||||||
|
{
|
||||||
|
public function AbsoluteLink()
|
||||||
|
{
|
||||||
|
// ..
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
@ -1,9 +1,10 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<ruleset name="SilverStripe">
|
<ruleset name="SilverStripe">
|
||||||
<description>CodeSniffer ruleset for SilverStripe coding conventions.</description>
|
<description>CodeSniffer ruleset for SilverStripe coding conventions.</description>
|
||||||
|
<file>src</file>
|
||||||
|
<file>tests</file>
|
||||||
<!-- base rules are PSR-2 -->
|
<!-- base rules are PSR-2 -->
|
||||||
<rule ref="PSR2" >
|
<rule ref="PSR2">
|
||||||
<!-- Current exclusions -->
|
<!-- Current exclusions -->
|
||||||
<exclude name="PSR1.Methods.CamelCapsMethodName" />
|
<exclude name="PSR1.Methods.CamelCapsMethodName" />
|
||||||
</rule>
|
</rule>
|
||||||
|
@ -75,8 +75,7 @@ class GoogleSitemapController extends Controller
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (
|
if (GoogleSitemap::enabled()
|
||||||
GoogleSitemap::enabled()
|
|
||||||
&& $class
|
&& $class
|
||||||
&& ($page > 0)
|
&& ($page > 0)
|
||||||
&& ($class == SiteTree::class || $class == 'GoogleSitemapRoute' || GoogleSitemap::is_registered($class))
|
&& ($class == SiteTree::class || $class == 'GoogleSitemapRoute' || GoogleSitemap::is_registered($class))
|
||||||
|
@ -90,8 +90,7 @@ class GoogleSitemap
|
|||||||
* @var array
|
* @var array
|
||||||
*/
|
*/
|
||||||
private static $search_indexes = [
|
private static $search_indexes = [
|
||||||
'google' => 'http://www.google.com/webmasters/sitemaps/ping?sitemap=',
|
'google' => 'http://www.google.com/webmasters/sitemaps/ping?sitemap='
|
||||||
'bing' => 'http://www.bing.com/ping?sitemap=',
|
|
||||||
];
|
];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
14
src/Sitemapable.php
Normal file
14
src/Sitemapable.php
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
|
||||||
|
namespace Wilr\GoogleSitemaps;
|
||||||
|
|
||||||
|
interface Sitemapable
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Return the absolute URL for this object
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function AbsoluteLink();
|
||||||
|
}
|
@ -20,12 +20,22 @@ use Wilr\GoogleSitemaps\Tests\Model\UnviewableDataObject;
|
|||||||
class GoogleSitemapTest extends FunctionalTest
|
class GoogleSitemapTest extends FunctionalTest
|
||||||
{
|
{
|
||||||
protected static $fixture_file = [
|
protected static $fixture_file = [
|
||||||
'GoogleSitemapTest.yml',
|
'GoogleSitemapTest.yml'
|
||||||
'GoogleSitemapPageTest.yml',
|
|
||||||
];
|
];
|
||||||
|
|
||||||
protected $usesDatabase = true;
|
protected $usesDatabase = true;
|
||||||
|
|
||||||
|
public static function get_fixture_file()
|
||||||
|
{
|
||||||
|
$files = [__DIR__ . '/GoogleSitemapTest.yml'];
|
||||||
|
|
||||||
|
if (class_exists('Page')) {
|
||||||
|
$files[] = __DIR__ . '/GoogleSitemapPageTest.yml';
|
||||||
|
}
|
||||||
|
|
||||||
|
return $files;
|
||||||
|
}
|
||||||
|
|
||||||
protected static $extra_dataobjects = [
|
protected static $extra_dataobjects = [
|
||||||
TestDataObject::class,
|
TestDataObject::class,
|
||||||
OtherDataObject::class,
|
OtherDataObject::class,
|
||||||
@ -55,13 +65,13 @@ class GoogleSitemapTest extends FunctionalTest
|
|||||||
public function testCanIncludeInGoogleSitemap(): void
|
public function testCanIncludeInGoogleSitemap(): void
|
||||||
{
|
{
|
||||||
GoogleSitemap::register_dataobject(TestDataObject::class, '');
|
GoogleSitemap::register_dataobject(TestDataObject::class, '');
|
||||||
|
|
||||||
$unused = $this->objFromFixture(TestDataObject::class, 'UnindexedDataObject');
|
|
||||||
$this->assertFalse($unused->canIncludeInGoogleSitemap());
|
|
||||||
|
|
||||||
$used = $this->objFromFixture(TestDataObject::class, 'DataObjectTest2');
|
$used = $this->objFromFixture(TestDataObject::class, 'DataObjectTest2');
|
||||||
|
|
||||||
$this->assertTrue($used->canIncludeInGoogleSitemap());
|
$this->assertTrue($used->canIncludeInGoogleSitemap());
|
||||||
|
|
||||||
|
$used->setPrivate();
|
||||||
|
|
||||||
|
$this->assertFalse($used->canIncludeInGoogleSitemap());
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testIndexFileWithCustomRoute(): void
|
public function testIndexFileWithCustomRoute(): void
|
||||||
@ -77,31 +87,29 @@ class GoogleSitemapTest extends FunctionalTest
|
|||||||
public function testGetItems(): void
|
public function testGetItems(): void
|
||||||
{
|
{
|
||||||
GoogleSitemap::register_dataobject(TestDataObject::class, '');
|
GoogleSitemap::register_dataobject(TestDataObject::class, '');
|
||||||
|
$google = new GoogleSitemap();
|
||||||
|
|
||||||
$items = GoogleSitemap::get_items(TestDataObject::class, 1);
|
$items = $google->getItems(TestDataObject::class, 1);
|
||||||
$this->assertEquals(2, $items->count());
|
|
||||||
|
|
||||||
$this->assertListEquals(array(
|
$this->assertEquals(3, $items->count());
|
||||||
array("Priority" => "0.2"),
|
|
||||||
array("Priority" => "0.4")
|
|
||||||
), $items);
|
|
||||||
|
|
||||||
GoogleSitemap::register_dataobject(OtherDataObject::class);
|
GoogleSitemap::register_dataobject(OtherDataObject::class);
|
||||||
$this->assertEquals(1, GoogleSitemap::get_items(OtherDataObject::class, 1)->count());
|
$this->assertEquals(1, $google->getItems(OtherDataObject::class, 1)->count());
|
||||||
|
|
||||||
GoogleSitemap::register_dataobject(UnviewableDataObject::class);
|
GoogleSitemap::register_dataobject(UnviewableDataObject::class);
|
||||||
$this->assertEquals(0, GoogleSitemap::get_items(UnviewableDataObject::class, 1)->count());
|
$this->assertEquals(0, $google->getItems(UnviewableDataObject::class, 1)->count());
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testGetItemsWithCustomRoutes(): void
|
public function testGetItemsWithCustomRoutes(): void
|
||||||
{
|
{
|
||||||
GoogleSitemap::register_routes(array(
|
GoogleSitemap::register_routes([
|
||||||
'/test-route/',
|
'/test-route/',
|
||||||
'/someother-route/',
|
'/someother-route/',
|
||||||
'/fake-sitemap-route/'
|
'/fake-sitemap-route/'
|
||||||
));
|
]);
|
||||||
|
|
||||||
$items = GoogleSitemap::get_items('GoogleSitemapRoute', 1);
|
$google = new GoogleSitemap();
|
||||||
|
$items = $google->getItems('GoogleSitemapRoute', 1);
|
||||||
$this->assertEquals(3, $items->count());
|
$this->assertEquals(3, $items->count());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -110,6 +118,16 @@ class GoogleSitemapTest extends FunctionalTest
|
|||||||
GoogleSitemap::register_dataobject(TestDataObject::class);
|
GoogleSitemap::register_dataobject(TestDataObject::class);
|
||||||
GoogleSitemap::register_dataobject(OtherDataObject::class);
|
GoogleSitemap::register_dataobject(OtherDataObject::class);
|
||||||
|
|
||||||
|
$obj = $this->objFromFixture(TestDataObject::class, 'DataObjectTest1');
|
||||||
|
$table = $obj->baseTable();
|
||||||
|
|
||||||
|
DB::query("UPDATE \"" . $table . "\" SET \"LastEdited\"='2023-02-13 00:00:00'");
|
||||||
|
|
||||||
|
$obj2 = $this->objFromFixture(OtherDataObject::class, 'OtherDataObjectTest2');
|
||||||
|
$table = $obj2->baseTable();
|
||||||
|
|
||||||
|
DB::query("UPDATE \"" . $table . "\" SET \"LastEdited\"='2023-02-13 00:00:00'");
|
||||||
|
|
||||||
$response = $this->get('sitemap.xml');
|
$response = $this->get('sitemap.xml');
|
||||||
$body = $response->getBody();
|
$body = $response->getBody();
|
||||||
|
|
||||||
@ -153,9 +171,19 @@ class GoogleSitemapTest extends FunctionalTest
|
|||||||
Config::inst()->set(GoogleSitemap::class, 'objects_per_sitemap', 1);
|
Config::inst()->set(GoogleSitemap::class, 'objects_per_sitemap', 1);
|
||||||
GoogleSitemap::register_dataobject(TestDataObject::class);
|
GoogleSitemap::register_dataobject(TestDataObject::class);
|
||||||
|
|
||||||
|
|
||||||
|
$obj = $this->objFromFixture(TestDataObject::class, 'DataObjectTest1');
|
||||||
|
$obj1 = $this->objFromFixture(TestDataObject::class, 'DataObjectTest2');
|
||||||
|
$obj2 = $this->objFromFixture(TestDataObject::class, 'UnindexedDataObject');
|
||||||
|
|
||||||
|
$table = $obj->baseTable();
|
||||||
|
DB::query("UPDATE \"" . $table . "\" SET \"LastEdited\"='2023-02-13 00:00:00' WHERE \"ID\"='" . $obj->ID . "'");
|
||||||
|
DB::query("UPDATE \"" . $table . "\" SET \"LastEdited\"='2023-02-13 00:00:00' WHERE \"ID\"='" . $obj1->ID . "'");
|
||||||
|
DB::query("UPDATE \"" . $table . "\" SET \"LastEdited\"='2023-02-13 00:00:00' WHERE \"ID\"='" . $obj2->ID . "'");
|
||||||
|
|
||||||
|
|
||||||
$response = $this->get('sitemap.xml');
|
$response = $this->get('sitemap.xml');
|
||||||
$body = $response->getBody();
|
$body = $response->getBody();
|
||||||
|
|
||||||
$this->assertXmlStringEqualsXmlFile(__DIR__ . '/xml/' . __FUNCTION__ . '.xml', $body);
|
$this->assertXmlStringEqualsXmlFile(__DIR__ . '/xml/' . __FUNCTION__ . '.xml', $body);
|
||||||
|
|
||||||
Config::inst()->set(GoogleSitemap::class, 'objects_per_sitemap', $original);
|
Config::inst()->set(GoogleSitemap::class, 'objects_per_sitemap', $original);
|
||||||
@ -164,11 +192,11 @@ class GoogleSitemapTest extends FunctionalTest
|
|||||||
public function testRegisterRoutesIncludesAllRoutes(): void
|
public function testRegisterRoutesIncludesAllRoutes(): void
|
||||||
{
|
{
|
||||||
GoogleSitemap::register_route('/test/');
|
GoogleSitemap::register_route('/test/');
|
||||||
GoogleSitemap::register_routes(array(
|
GoogleSitemap::register_routes([
|
||||||
'/test/', // duplication should be replaced
|
'/test/', // duplication should be replaced
|
||||||
'/unittests/',
|
'/unittests/',
|
||||||
'/anotherlink/'
|
'/anotherlink/'
|
||||||
), 'weekly');
|
], 'weekly');
|
||||||
|
|
||||||
$response = $this->get('sitemap.xml/sitemap/GoogleSitemapRoute/1');
|
$response = $this->get('sitemap.xml/sitemap/GoogleSitemapRoute/1');
|
||||||
$body = $response->getBody();
|
$body = $response->getBody();
|
||||||
@ -193,7 +221,7 @@ class GoogleSitemapTest extends FunctionalTest
|
|||||||
|
|
||||||
public function testGetItemsWithPages(): void
|
public function testGetItemsWithPages(): void
|
||||||
{
|
{
|
||||||
if (!class_exists('Page')) {
|
if (!class_exists(SiteTree::class)) {
|
||||||
$this->markTestIncomplete('No cms module installed, page related test skipped');
|
$this->markTestIncomplete('No cms module installed, page related test skipped');
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -205,10 +233,10 @@ class GoogleSitemapTest extends FunctionalTest
|
|||||||
$page2->publishSingle();
|
$page2->publishSingle();
|
||||||
$page2->flushCache();
|
$page2->flushCache();
|
||||||
|
|
||||||
$this->assertListContains(array(
|
$this->assertListContains([
|
||||||
array('Title' => 'Testpage1'),
|
['Title' => 'Testpage1'],
|
||||||
array('Title' => 'Testpage2')
|
['Title' => 'Testpage2']
|
||||||
), GoogleSitemap::inst()->getItems(SiteTree::class), "There should be 2 pages in the sitemap after publishing");
|
], GoogleSitemap::inst()->getItems(SiteTree::class), "There should be 2 pages in the sitemap after publishing");
|
||||||
|
|
||||||
// check if we make a page readonly that it is hidden
|
// check if we make a page readonly that it is hidden
|
||||||
$page2->CanViewType = 'LoggedInUsers';
|
$page2->CanViewType = 'LoggedInUsers';
|
||||||
@ -217,9 +245,9 @@ class GoogleSitemapTest extends FunctionalTest
|
|||||||
|
|
||||||
$this->logOut();
|
$this->logOut();
|
||||||
|
|
||||||
$this->assertListEquals(array(
|
$this->assertListEquals([
|
||||||
array('Title' => 'Testpage1')
|
['Title' => 'Testpage1']
|
||||||
), GoogleSitemap::inst()->getItems(SiteTree::class), "There should be only 1 page, other is logged in only");
|
], GoogleSitemap::inst()->getItems(SiteTree::class), "There should be only 1 page, other is logged in only");
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testAccess(): void
|
public function testAccess(): void
|
||||||
|
@ -8,6 +8,7 @@ use SilverStripe\Control\Director;
|
|||||||
|
|
||||||
class TestDataObject extends DataObject implements TestOnly
|
class TestDataObject extends DataObject implements TestOnly
|
||||||
{
|
{
|
||||||
|
protected $private = false;
|
||||||
|
|
||||||
private static $db = array(
|
private static $db = array(
|
||||||
'Priority' => 'Varchar(10)'
|
'Priority' => 'Varchar(10)'
|
||||||
@ -15,9 +16,19 @@ class TestDataObject extends DataObject implements TestOnly
|
|||||||
|
|
||||||
public function canView($member = null)
|
public function canView($member = null)
|
||||||
{
|
{
|
||||||
|
if ($this->private) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public function setPrivate()
|
||||||
|
{
|
||||||
|
$this->private = true;
|
||||||
|
}
|
||||||
|
|
||||||
public function AbsoluteLink()
|
public function AbsoluteLink()
|
||||||
{
|
{
|
||||||
return Director::absoluteBaseURL();
|
return Director::absoluteBaseURL();
|
||||||
|
Loading…
Reference in New Issue
Block a user