mirror of
https://github.com/silverstripe/silverstripe-docsviewer
synced 2024-10-22 09:05:56 +00:00
Merge pull request #136 from creative-commoners/pulls/2.0/canonical-url
NEW Add ability to handle canonical URLs
This commit is contained in:
commit
a10cdd35f7
@ -574,6 +574,19 @@ class DocumentationViewer extends Controller implements PermissionProvider
|
||||
return $link;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the canonical URL from the page
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getCanonicalUrl()
|
||||
{
|
||||
if (!$this->getPage()) {
|
||||
return '';
|
||||
}
|
||||
return $this->getPage()->getCanonicalUrl();
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate a list of all the pages in the documentation grouped by the
|
||||
* first letter of the page.
|
||||
|
@ -38,6 +38,11 @@ class DocumentationPage extends ViewableData
|
||||
|
||||
protected $read = false;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
protected $canonicalUrl;
|
||||
|
||||
/**
|
||||
* @param DocumentationEntity $entity
|
||||
* @param string $filename
|
||||
@ -260,10 +265,25 @@ class DocumentationPage extends ViewableData
|
||||
Controller::join_links(
|
||||
$this->entity->Link($short),
|
||||
$this->getRelativeLink()
|
||||
), '/'
|
||||
),
|
||||
'/'
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine and set the canonical URL for the given record, for example: dev/docs/en/Path/To/Document
|
||||
*/
|
||||
public function populateCanonicalUrl()
|
||||
{
|
||||
$url = Director::absoluteURL(Controller::join_links(
|
||||
Config::inst()->get('DocumentationViewer', 'link_base'),
|
||||
$this->getEntity()->getLanguage(),
|
||||
$this->getRelativeLink()
|
||||
));
|
||||
|
||||
$this->setCanonicalUrl($url);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return metadata from the first html block in the page, then remove the
|
||||
* block on request
|
||||
@ -349,5 +369,30 @@ class DocumentationPage extends ViewableData
|
||||
{
|
||||
return sprintf(get_class($this) .': %s)', $this->getPath());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the canonical URL to use for this page
|
||||
*
|
||||
* @param string $canonicalUrl
|
||||
* @return $this
|
||||
*/
|
||||
public function setCanonicalUrl($canonicalUrl)
|
||||
{
|
||||
$this->canonicalUrl = $canonicalUrl;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the canonical URL to use for this page. Will trigger discovery
|
||||
* via {@link DocumentationPage::populateCanonicalUrl()} if none is already set.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getCanonicalUrl()
|
||||
{
|
||||
if (!$this->canonicalUrl) {
|
||||
$this->populateCanonicalUrl();
|
||||
}
|
||||
return $this->canonicalUrl;
|
||||
}
|
||||
}
|
||||
|
@ -2,6 +2,9 @@
|
||||
<% base_tag %>
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<% if $CanonicalUrl %>
|
||||
<link rel="canonical" href="$CanonicalUrl" />
|
||||
<% end_if %>
|
||||
<title><% if Title %>$Title – <% end_if %>$DocumentationTitle</title>
|
||||
</head>
|
||||
|
||||
|
@ -19,10 +19,8 @@ class DocumentationPageTest extends SapphireTest
|
||||
|
||||
Config::nest();
|
||||
|
||||
// explicitly use dev/docs. Custom paths should be tested separately
|
||||
Config::inst()->update(
|
||||
'DocumentationViewer', 'link_base', 'dev/docs/'
|
||||
);
|
||||
// explicitly use dev/docs. Custom paths should be tested separately
|
||||
Config::inst()->update('DocumentationViewer', 'link_base', 'dev/docs/');
|
||||
|
||||
$manifest = new DocumentationManifest(true);
|
||||
}
|
||||
@ -41,7 +39,7 @@ class DocumentationPageTest extends SapphireTest
|
||||
'test.md',
|
||||
DOCSVIEWER_PATH . '/tests/docs/en/test.md'
|
||||
);
|
||||
|
||||
|
||||
// single layer
|
||||
$this->assertEquals(
|
||||
'dev/docs/en/doctest/2.4/test/', $page->Link(),
|
||||
@ -53,18 +51,18 @@ class DocumentationPageTest extends SapphireTest
|
||||
'sort',
|
||||
DOCSVIEWER_PATH . '/tests/docs/en/sort/'
|
||||
);
|
||||
|
||||
|
||||
$this->assertEquals('dev/docs/en/doctest/2.4/sort/', $page->Link());
|
||||
|
||||
|
||||
$page = new DocumentationFolder(
|
||||
$this->entity,
|
||||
'1-basic.md',
|
||||
DOCSVIEWER_PATH . '/tests/docs/en/sort/1-basic.md'
|
||||
);
|
||||
|
||||
|
||||
$this->assertEquals('dev/docs/en/doctest/2.4/sort/basic/', $page->Link());
|
||||
}
|
||||
|
||||
|
||||
public function testGetBreadcrumbTitle()
|
||||
{
|
||||
$page = new DocumentationPage(
|
||||
@ -74,13 +72,13 @@ class DocumentationPageTest extends SapphireTest
|
||||
);
|
||||
|
||||
$this->assertEquals("Test - Doctest", $page->getBreadcrumbTitle());
|
||||
|
||||
|
||||
$page = new DocumentationFolder(
|
||||
$this->entity,
|
||||
'1-basic.md',
|
||||
DOCSVIEWER_PATH . '/tests/docs/en/sort/1-basic.md'
|
||||
);
|
||||
|
||||
|
||||
$this->assertEquals('Basic - Sort - Doctest', $page->getBreadcrumbTitle());
|
||||
|
||||
$page = new DocumentationFolder(
|
||||
@ -91,4 +89,22 @@ class DocumentationPageTest extends SapphireTest
|
||||
|
||||
$this->assertEquals('Sort - Doctest', $page->getBreadcrumbTitle());
|
||||
}
|
||||
|
||||
public function testGetCanonicalUrl()
|
||||
{
|
||||
$page = new DocumentationPage(
|
||||
$this->entity,
|
||||
'file.md',
|
||||
DOCSVIEWER_PATH . '/tests/docs/en/test/file.md'
|
||||
);
|
||||
|
||||
$this->assertContains(
|
||||
'dev/docs/en/test/file/',
|
||||
$page->getCanonicalUrl(),
|
||||
'Canonical URL is determined, set and returned'
|
||||
);
|
||||
|
||||
$page->setCanonicalUrl('some-other-url');
|
||||
$this->assertSame('some-other-url', $page->getCanonicalUrl(), 'Canonical URL can be adjusted via public API');
|
||||
}
|
||||
}
|
||||
|
@ -11,7 +11,7 @@
|
||||
class DocumentationViewerTest extends FunctionalTest
|
||||
{
|
||||
protected $autoFollowRedirection = false;
|
||||
|
||||
|
||||
protected $manifest;
|
||||
|
||||
public function setUp()
|
||||
@ -20,7 +20,7 @@ class DocumentationViewerTest extends FunctionalTest
|
||||
|
||||
Config::nest();
|
||||
|
||||
// explicitly use dev/docs. Custom paths should be tested separately
|
||||
// explicitly use dev/docs. Custom paths should be tested separately
|
||||
Config::inst()->update(
|
||||
'DocumentationViewer', 'link_base', 'dev/docs/'
|
||||
);
|
||||
@ -65,11 +65,11 @@ class DocumentationViewerTest extends FunctionalTest
|
||||
|
||||
$this->manifest = new DocumentationManifest(true);
|
||||
}
|
||||
|
||||
|
||||
public function tearDown()
|
||||
{
|
||||
parent::tearDown();
|
||||
|
||||
|
||||
Config::unnest();
|
||||
}
|
||||
|
||||
@ -98,47 +98,47 @@ class DocumentationViewerTest extends FunctionalTest
|
||||
|
||||
$response = $this->get('dev/docs/en/doc_test/3.0/empty.md');
|
||||
$this->assertEquals(301, $response->getStatusCode(), 'Direct markdown links also work. They should redirect to /empty/');
|
||||
|
||||
|
||||
|
||||
// 2.4 is the stable release. Not in the URL
|
||||
$response = $this->get('dev/docs/en/doc_test/2.4');
|
||||
$this->assertEquals($response->getStatusCode(), 200, 'Existing base folder');
|
||||
$this->assertContains('english test', $response->getBody(), 'Toplevel content page');
|
||||
|
||||
|
||||
// accessing base redirects to the version with the version number.
|
||||
$response = $this->get('dev/docs/en/doc_test/');
|
||||
$this->assertEquals($response->getStatusCode(), 301, 'Existing base folder redirects to with version');
|
||||
|
||||
$response = $this->get('dev/docs/en/doc_test/3.0/');
|
||||
$this->assertEquals($response->getStatusCode(), 200, 'Existing base folder');
|
||||
|
||||
|
||||
$response = $this->get('dev/docs/en/doc_test/2.3/nonexistant-subfolder');
|
||||
$this->assertEquals($response->getStatusCode(), 404, 'Nonexistant subfolder');
|
||||
|
||||
|
||||
$response = $this->get('dev/docs/en/doc_test/2.3/nonexistant-file.txt');
|
||||
$this->assertEquals($response->getStatusCode(), 301, 'Nonexistant file');
|
||||
|
||||
$response = $this->get('dev/docs/en/doc_test/2.3/nonexistant-file/');
|
||||
$this->assertEquals($response->getStatusCode(), 404, 'Nonexistant file');
|
||||
|
||||
|
||||
$response = $this->get('dev/docs/en/doc_test/2.3/test');
|
||||
$this->assertEquals($response->getStatusCode(), 200, 'Existing file');
|
||||
|
||||
|
||||
$response = $this->get('dev/docs/en/doc_test/3.0/empty?foo');
|
||||
$this->assertEquals(200, $response->getStatusCode(), 'Existing page');
|
||||
|
||||
|
||||
$response = $this->get('dev/docs/en/doc_test/3.0/empty/');
|
||||
$this->assertEquals($response->getStatusCode(), 200, 'Existing page');
|
||||
|
||||
|
||||
$response = $this->get('dev/docs/en/doc_test/3.0/test');
|
||||
$this->assertEquals($response->getStatusCode(), 404, 'Missing page');
|
||||
|
||||
|
||||
$response = $this->get('dev/docs/en/doc_test/3.0/test.md');
|
||||
$this->assertEquals($response->getStatusCode(), 301, 'Missing page');
|
||||
|
||||
|
||||
$response = $this->get('dev/docs/en/doc_test/3.0/test/');
|
||||
$this->assertEquals($response->getStatusCode(), 404, 'Missing page');
|
||||
|
||||
|
||||
$response = $this->get('dev/docs/dk/');
|
||||
$this->assertEquals($response->getStatusCode(), 404, 'Access a language that doesn\'t exist');
|
||||
}
|
||||
@ -188,7 +188,7 @@ class DocumentationViewerTest extends FunctionalTest
|
||||
$response = $v->handleRequest(new SS_HTTPRequest('GET', 'en/doc_test/2.3/subfolder/subsubfolder/subsubpage/'), DataModel::inst());
|
||||
$this->assertEquals('en', $v->getLanguage());
|
||||
}
|
||||
|
||||
|
||||
|
||||
public function testAccessingAll()
|
||||
{
|
||||
@ -230,4 +230,20 @@ class DocumentationViewerTest extends FunctionalTest
|
||||
// redirect should have been to the absolute url minus the .md extension
|
||||
$this->assertEquals(Director::absoluteURL('dev/docs/en/doc_test/3.0/tutorials/'), $response->getHeader('Location'));
|
||||
}
|
||||
|
||||
public function testCanonicalUrlIsIncludedInLayout()
|
||||
{
|
||||
$response = $this->get('dev/docs/en/doc_test/2.3/subfolder/subsubfolder/subsubpage');
|
||||
|
||||
$this->assertEquals(200, $response->getStatusCode());
|
||||
|
||||
$expectedUrl = Director::absoluteURL('dev/docs/en/subfolder/subsubfolder/subsubpage/');
|
||||
$this->assertContains('<link rel="canonical" href="' . $expectedUrl . '" />', (string) $response->getBody());
|
||||
}
|
||||
|
||||
public function testCanonicalUrlIsEmptyWhenNoPageExists()
|
||||
{
|
||||
$viewer = new DocumentationViewer;
|
||||
$this->assertSame('', $viewer->getCanonicalUrl());
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user