From 8a7c8aa9cc1af179cd25794a72b70e3ed4c79126 Mon Sep 17 00:00:00 2001 From: Will Rossiter Date: Sat, 28 Oct 2023 09:23:54 +1300 Subject: [PATCH] feat: implement Sitemapable (#181) --- README.md | 6 +- _config.php | 10 +++ docs/en/index.md | 103 +++++++++++++----------- phpcs.xml.dist | 5 +- src/Control/GoogleSitemapController.php | 3 +- src/GoogleSitemap.php | 3 +- src/Sitemapable.php | 14 ++++ tests/GoogleSitemapTest.php | 84 ++++++++++++------- tests/GoogleSitemapTest.yml | 20 ++--- tests/Model/TestDataObject.php | 11 +++ 10 files changed, 164 insertions(+), 95 deletions(-) create mode 100644 _config.php create mode 100644 src/Sitemapable.php diff --git a/README.md b/README.md index ecfa11e..4c1cb1f 100644 --- a/README.md +++ b/README.md @@ -6,13 +6,13 @@ ## Maintainer Contact -* Will Rossiter (Nickname: wrossiter, willr) +- Will Rossiter (Nickname: wrossiter, willr) ## 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) diff --git a/_config.php b/_config.php new file mode 100644 index 0000000..4ebb97a --- /dev/null +++ b/_config.php @@ -0,0 +1,10 @@ +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 + +``` + CodeSniffer ruleset for SilverStripe coding conventions. - + src + tests - + diff --git a/src/Control/GoogleSitemapController.php b/src/Control/GoogleSitemapController.php index 46ce1e5..9173622 100644 --- a/src/Control/GoogleSitemapController.php +++ b/src/Control/GoogleSitemapController.php @@ -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)) diff --git a/src/GoogleSitemap.php b/src/GoogleSitemap.php index 896c7d0..f2d41a1 100644 --- a/src/GoogleSitemap.php +++ b/src/GoogleSitemap.php @@ -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=' ]; /** diff --git a/src/Sitemapable.php b/src/Sitemapable.php new file mode 100644 index 0000000..2d41716 --- /dev/null +++ b/src/Sitemapable.php @@ -0,0 +1,14 @@ +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 diff --git a/tests/GoogleSitemapTest.yml b/tests/GoogleSitemapTest.yml index 52952df..9342e9f 100644 --- a/tests/GoogleSitemapTest.yml +++ b/tests/GoogleSitemapTest.yml @@ -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 diff --git a/tests/Model/TestDataObject.php b/tests/Model/TestDataObject.php index cf28780..d27df28 100644 --- a/tests/Model/TestDataObject.php +++ b/tests/Model/TestDataObject.php @@ -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();