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
|
||||
|
||||
* Will Rossiter (Nickname: wrossiter, willr) <will@fullscreen.io>
|
||||
- Will Rossiter (Nickname: wrossiter, willr) <will@fullscreen.io>
|
||||
|
||||
## Installation
|
||||
|
||||
> 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.
|
||||
|
||||
@ -34,4 +34,4 @@ See docs/en for more information about configuring the module.
|
||||
|
||||
## 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);
|
||||
}
|
||||
}
|
103
docs/en/index.md
103
docs/en/index.md
@ -30,42 +30,32 @@ manually, including requesting to have the page excluded from the sitemap.
|
||||
Most module configuration is done via the SilverStripe Config API. Create a new
|
||||
config file `mysite/_config/googlesitemaps.yml` with the following outline:
|
||||
|
||||
---
|
||||
Name: customgooglesitemaps
|
||||
After: googlesitemaps
|
||||
---
|
||||
Wilr\GoogleSitemaps\GoogleSitemap:
|
||||
enabled: true
|
||||
objects_per_sitemap: 1000
|
||||
google_notification_enabled: false
|
||||
use_show_in_search: true
|
||||
---
|
||||
Name: customgooglesitemaps
|
||||
After: googlesitemaps
|
||||
---
|
||||
Wilr\GoogleSitemaps\GoogleSitemap:
|
||||
|
||||
enabled: true
|
||||
objects_per_sitemap: 1000
|
||||
google_notification_enabled: false
|
||||
use_show_in_search: true
|
||||
|
||||
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
|
||||
your page. You can set this in the file we created in the last paragraph by
|
||||
editing the `google_notification_enabled` option to true
|
||||
|
||||
---
|
||||
Name: customgooglesitemaps
|
||||
After: googlesitemaps
|
||||
---
|
||||
Wilr\GoogleSitemaps\GoogleSitemap:
|
||||
enabled: true
|
||||
objects_per_sitemap: 1000
|
||||
google_notification_enabled: true
|
||||
use_show_in_search: true
|
||||
|
||||
### Bing Ping Support
|
||||
|
||||
To ping Bing whenever your sitemap is updated, set `bing_notification_enabled`
|
||||
|
||||
---
|
||||
Name: customgooglesitemaps
|
||||
After: googlesitemaps
|
||||
---
|
||||
Wilr\GoogleSitemaps\GoogleSitemap:
|
||||
enabled: true
|
||||
bing_notification_enabled: true
|
||||
|
||||
enabled: true
|
||||
objects_per_sitemap: 1000
|
||||
google_notification_enabled: true
|
||||
use_show_in_search: true
|
||||
|
||||
### Including DataObjects
|
||||
|
||||
@ -76,41 +66,40 @@ database as DataObject subclasses.
|
||||
To include a DataObject instance 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.
|
||||
- AbsoluteLink() function which returns the URL for this DataObject
|
||||
- canView() function which returns a boolean value.
|
||||
|
||||
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 its ID.
|
||||
|
||||
<?php
|
||||
<?php
|
||||
|
||||
use SilverStripe\ORM\DataObject;
|
||||
use SilverStripe\Control\Director;
|
||||
|
||||
class MyDataObject extends DataObject {
|
||||
class MyDataObject extends DataObject {
|
||||
|
||||
function canView($member = null) {
|
||||
return true;
|
||||
}
|
||||
function canView($member = null) {
|
||||
return true;
|
||||
}
|
||||
|
||||
function AbsoluteLink() {
|
||||
return Director::absoluteURL($this->Link());
|
||||
}
|
||||
|
||||
function Link() {
|
||||
return 'MyController/show/'. $this->ID;
|
||||
}
|
||||
}
|
||||
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
|
||||
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;
|
||||
|
||||
GoogleSitemap::register_dataobject('MyDataObject');
|
||||
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_dataobject(), So
|
||||
@ -118,7 +107,7 @@ instead of the previous code you would write:
|
||||
|
||||
use Wilr\GoogleSitemaps\GoogleSitemap;
|
||||
|
||||
GoogleSitemap::register_dataobject('MyDataObject', 'daily');
|
||||
GoogleSitemap::register_dataobject('MyDataObject', 'daily');
|
||||
|
||||
See the following blog post for more information:
|
||||
|
||||
@ -133,8 +122,26 @@ urls to include.
|
||||
|
||||
use Wilr\GoogleSitemaps\GoogleSitemap;
|
||||
|
||||
GoogleSitemap::register_routes(array(
|
||||
'/my-custom-controller/',
|
||||
'/Security/',
|
||||
'/Security/login/'
|
||||
));
|
||||
GoogleSitemap::register_routes(array(
|
||||
'/my-custom-controller/',
|
||||
'/Security/',
|
||||
'/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"?>
|
||||
<ruleset name="SilverStripe">
|
||||
<description>CodeSniffer ruleset for SilverStripe coding conventions.</description>
|
||||
|
||||
<file>src</file>
|
||||
<file>tests</file>
|
||||
<!-- base rules are PSR-2 -->
|
||||
<rule ref="PSR2" >
|
||||
<rule ref="PSR2">
|
||||
<!-- Current exclusions -->
|
||||
<exclude name="PSR1.Methods.CamelCapsMethodName" />
|
||||
</rule>
|
||||
|
@ -75,8 +75,7 @@ class GoogleSitemapController extends Controller
|
||||
}
|
||||
}
|
||||
|
||||
if (
|
||||
GoogleSitemap::enabled()
|
||||
if (GoogleSitemap::enabled()
|
||||
&& $class
|
||||
&& ($page > 0)
|
||||
&& ($class == SiteTree::class || $class == 'GoogleSitemapRoute' || GoogleSitemap::is_registered($class))
|
||||
|
@ -90,8 +90,7 @@ class GoogleSitemap
|
||||
* @var array
|
||||
*/
|
||||
private static $search_indexes = [
|
||||
'google' => 'http://www.google.com/webmasters/sitemaps/ping?sitemap=',
|
||||
'bing' => 'http://www.bing.com/ping?sitemap=',
|
||||
'google' => 'http://www.google.com/webmasters/sitemaps/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
|
||||
{
|
||||
protected static $fixture_file = [
|
||||
'GoogleSitemapTest.yml',
|
||||
'GoogleSitemapPageTest.yml',
|
||||
'GoogleSitemapTest.yml'
|
||||
];
|
||||
|
||||
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 = [
|
||||
TestDataObject::class,
|
||||
OtherDataObject::class,
|
||||
@ -55,13 +65,13 @@ class GoogleSitemapTest extends FunctionalTest
|
||||
public function testCanIncludeInGoogleSitemap(): void
|
||||
{
|
||||
GoogleSitemap::register_dataobject(TestDataObject::class, '');
|
||||
|
||||
$unused = $this->objFromFixture(TestDataObject::class, 'UnindexedDataObject');
|
||||
$this->assertFalse($unused->canIncludeInGoogleSitemap());
|
||||
|
||||
$used = $this->objFromFixture(TestDataObject::class, 'DataObjectTest2');
|
||||
|
||||
$this->assertTrue($used->canIncludeInGoogleSitemap());
|
||||
|
||||
$used->setPrivate();
|
||||
|
||||
$this->assertFalse($used->canIncludeInGoogleSitemap());
|
||||
}
|
||||
|
||||
public function testIndexFileWithCustomRoute(): void
|
||||
@ -77,31 +87,29 @@ class GoogleSitemapTest extends FunctionalTest
|
||||
public function testGetItems(): void
|
||||
{
|
||||
GoogleSitemap::register_dataobject(TestDataObject::class, '');
|
||||
$google = new GoogleSitemap();
|
||||
|
||||
$items = GoogleSitemap::get_items(TestDataObject::class, 1);
|
||||
$this->assertEquals(2, $items->count());
|
||||
$items = $google->getItems(TestDataObject::class, 1);
|
||||
|
||||
$this->assertListEquals(array(
|
||||
array("Priority" => "0.2"),
|
||||
array("Priority" => "0.4")
|
||||
), $items);
|
||||
$this->assertEquals(3, $items->count());
|
||||
|
||||
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);
|
||||
$this->assertEquals(0, GoogleSitemap::get_items(UnviewableDataObject::class, 1)->count());
|
||||
$this->assertEquals(0, $google->getItems(UnviewableDataObject::class, 1)->count());
|
||||
}
|
||||
|
||||
public function testGetItemsWithCustomRoutes(): void
|
||||
{
|
||||
GoogleSitemap::register_routes(array(
|
||||
GoogleSitemap::register_routes([
|
||||
'/test-route/',
|
||||
'/someother-route/',
|
||||
'/fake-sitemap-route/'
|
||||
));
|
||||
]);
|
||||
|
||||
$items = GoogleSitemap::get_items('GoogleSitemapRoute', 1);
|
||||
$google = new GoogleSitemap();
|
||||
$items = $google->getItems('GoogleSitemapRoute', 1);
|
||||
$this->assertEquals(3, $items->count());
|
||||
}
|
||||
|
||||
@ -110,6 +118,16 @@ class GoogleSitemapTest extends FunctionalTest
|
||||
GoogleSitemap::register_dataobject(TestDataObject::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');
|
||||
$body = $response->getBody();
|
||||
|
||||
@ -153,9 +171,19 @@ class GoogleSitemapTest extends FunctionalTest
|
||||
Config::inst()->set(GoogleSitemap::class, 'objects_per_sitemap', 1);
|
||||
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');
|
||||
$body = $response->getBody();
|
||||
|
||||
$this->assertXmlStringEqualsXmlFile(__DIR__ . '/xml/' . __FUNCTION__ . '.xml', $body);
|
||||
|
||||
Config::inst()->set(GoogleSitemap::class, 'objects_per_sitemap', $original);
|
||||
@ -164,11 +192,11 @@ class GoogleSitemapTest extends FunctionalTest
|
||||
public function testRegisterRoutesIncludesAllRoutes(): void
|
||||
{
|
||||
GoogleSitemap::register_route('/test/');
|
||||
GoogleSitemap::register_routes(array(
|
||||
GoogleSitemap::register_routes([
|
||||
'/test/', // duplication should be replaced
|
||||
'/unittests/',
|
||||
'/anotherlink/'
|
||||
), 'weekly');
|
||||
], 'weekly');
|
||||
|
||||
$response = $this->get('sitemap.xml/sitemap/GoogleSitemapRoute/1');
|
||||
$body = $response->getBody();
|
||||
@ -193,7 +221,7 @@ class GoogleSitemapTest extends FunctionalTest
|
||||
|
||||
public function testGetItemsWithPages(): void
|
||||
{
|
||||
if (!class_exists('Page')) {
|
||||
if (!class_exists(SiteTree::class)) {
|
||||
$this->markTestIncomplete('No cms module installed, page related test skipped');
|
||||
}
|
||||
|
||||
@ -205,10 +233,10 @@ class GoogleSitemapTest extends FunctionalTest
|
||||
$page2->publishSingle();
|
||||
$page2->flushCache();
|
||||
|
||||
$this->assertListContains(array(
|
||||
array('Title' => 'Testpage1'),
|
||||
array('Title' => 'Testpage2')
|
||||
), GoogleSitemap::inst()->getItems(SiteTree::class), "There should be 2 pages in the sitemap after publishing");
|
||||
$this->assertListContains([
|
||||
['Title' => 'Testpage1'],
|
||||
['Title' => 'Testpage2']
|
||||
], 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
|
||||
$page2->CanViewType = 'LoggedInUsers';
|
||||
@ -217,9 +245,9 @@ class GoogleSitemapTest extends FunctionalTest
|
||||
|
||||
$this->logOut();
|
||||
|
||||
$this->assertListEquals(array(
|
||||
array('Title' => 'Testpage1')
|
||||
), GoogleSitemap::inst()->getItems(SiteTree::class), "There should be only 1 page, other is logged in only");
|
||||
$this->assertListEquals([
|
||||
['Title' => 'Testpage1']
|
||||
], GoogleSitemap::inst()->getItems(SiteTree::class), "There should be only 1 page, other is logged in only");
|
||||
}
|
||||
|
||||
public function testAccess(): void
|
||||
|
@ -1,15 +1,15 @@
|
||||
Wilr\GoogleSitemaps\Tests\Model\TestDataObject:
|
||||
DataObjectTest1:
|
||||
Priority: 0.4
|
||||
DataObjectTest2:
|
||||
Priority: 0.2
|
||||
UnindexedDataObject:
|
||||
Priority: -1
|
||||
DataObjectTest1:
|
||||
Priority: 0.4
|
||||
DataObjectTest2:
|
||||
Priority: 0.2
|
||||
UnindexedDataObject:
|
||||
Priority: -1
|
||||
|
||||
Wilr\GoogleSitemaps\Tests\Model\OtherDataObject:
|
||||
OtherDataObjectTest2:
|
||||
Priority: 0.3
|
||||
OtherDataObjectTest2:
|
||||
Priority: 0.3
|
||||
|
||||
Wilr\GoogleSitemaps\Tests\Model\UnviewableDataObject:
|
||||
Unviewable1:
|
||||
Priority: 0.4
|
||||
Unviewable1:
|
||||
Priority: 0.4
|
||||
|
@ -8,6 +8,7 @@ use SilverStripe\Control\Director;
|
||||
|
||||
class TestDataObject extends DataObject implements TestOnly
|
||||
{
|
||||
protected $private = false;
|
||||
|
||||
private static $db = array(
|
||||
'Priority' => 'Varchar(10)'
|
||||
@ -15,9 +16,19 @@ class TestDataObject extends DataObject implements TestOnly
|
||||
|
||||
public function canView($member = null)
|
||||
{
|
||||
if ($this->private) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
public function setPrivate()
|
||||
{
|
||||
$this->private = true;
|
||||
}
|
||||
|
||||
public function AbsoluteLink()
|
||||
{
|
||||
return Director::absoluteBaseURL();
|
||||
|
Loading…
Reference in New Issue
Block a user