2011-03-18 04:23:47 +01:00
|
|
|
<?php
|
2016-06-16 06:57:19 +02:00
|
|
|
|
|
|
|
use SilverStripe\ORM\Versioning\Versioned;
|
|
|
|
use SilverStripe\ORM\DataObject;
|
|
|
|
use SilverStripe\ORM\DB;
|
|
|
|
|
2011-03-18 04:23:47 +01:00
|
|
|
/**
|
2016-01-26 06:38:42 +01:00
|
|
|
* Tests {@see SiteTreeLinkTracking} broken links feature: LinkTracking
|
|
|
|
*
|
2011-03-22 10:47:26 +01:00
|
|
|
* @package cms
|
2011-03-18 04:23:47 +01:00
|
|
|
* @subpackage tests
|
|
|
|
*/
|
|
|
|
class SiteTreeBrokenLinksTest extends SapphireTest {
|
2013-03-18 11:47:15 +01:00
|
|
|
protected static $fixture_file = 'SiteTreeBrokenLinksTest.yml';
|
2014-08-12 06:39:11 +02:00
|
|
|
|
2016-01-26 06:38:42 +01:00
|
|
|
public function setUp() {
|
|
|
|
parent::setUp();
|
|
|
|
|
2016-03-17 01:02:50 +01:00
|
|
|
Versioned::set_stage(Versioned::DRAFT);
|
2016-01-26 06:38:42 +01:00
|
|
|
AssetStoreTest_SpyStore::activate('SiteTreeBrokenLinksTest');
|
|
|
|
$this->logInWithPermission('ADMIN');
|
|
|
|
}
|
|
|
|
|
|
|
|
public function tearDown() {
|
|
|
|
AssetStoreTest_SpyStore::reset();
|
|
|
|
parent::tearDown();
|
|
|
|
}
|
|
|
|
|
2012-09-19 12:07:46 +02:00
|
|
|
public function testBrokenLinksBetweenPages() {
|
2011-03-18 04:23:47 +01:00
|
|
|
$obj = $this->objFromFixture('Page','content');
|
2016-03-08 21:50:55 +01:00
|
|
|
|
2012-07-12 04:51:19 +02:00
|
|
|
$obj->Content = '<a href="[sitetree_link,id=3423423]">this is a broken link</a>';
|
2011-03-18 04:23:47 +01:00
|
|
|
$obj->syncLinkTracking();
|
|
|
|
$this->assertTrue($obj->HasBrokenLink, 'Page has a broken link');
|
2016-03-08 21:50:55 +01:00
|
|
|
|
2012-07-12 04:51:19 +02:00
|
|
|
$obj->Content = '<a href="[sitetree_link,id=' . $this->idFromFixture('Page','about') .']">this is not a broken link</a>';
|
2011-03-18 04:23:47 +01:00
|
|
|
$obj->syncLinkTracking();
|
|
|
|
$this->assertFalse($obj->HasBrokenLink, 'Page does NOT have a broken link');
|
|
|
|
}
|
2014-08-12 06:39:11 +02:00
|
|
|
|
|
|
|
public function testBrokenAnchorBetweenPages() {
|
|
|
|
$obj = $this->objFromFixture('Page','content');
|
|
|
|
$target = $this->objFromFixture('Page', 'about');
|
|
|
|
|
|
|
|
$obj->Content = "<a href=\"[sitetree_link,id={$target->ID}]#no-anchor-here\">this is a broken link</a>";
|
|
|
|
$obj->syncLinkTracking();
|
|
|
|
$this->assertTrue($obj->HasBrokenLink, 'Page has a broken link');
|
|
|
|
|
|
|
|
$obj->Content = "<a href=\"[sitetree_link,id={$target->ID}]#yes-anchor-here\">this is not a broken link</a>";
|
|
|
|
$obj->syncLinkTracking();
|
|
|
|
$this->assertFalse($obj->HasBrokenLink, 'Page does NOT have a broken link');
|
|
|
|
}
|
|
|
|
|
2012-09-19 12:07:46 +02:00
|
|
|
public function testBrokenVirtualPages() {
|
2011-03-18 04:23:47 +01:00
|
|
|
$obj = $this->objFromFixture('Page','content');
|
|
|
|
$vp = new VirtualPage();
|
2016-03-08 21:50:55 +01:00
|
|
|
|
2014-08-12 06:39:11 +02:00
|
|
|
$vp->CopyContentFromID = $obj->ID;
|
2011-03-18 04:23:47 +01:00
|
|
|
$vp->syncLinkTracking();
|
|
|
|
$this->assertFalse($vp->HasBrokenLink, 'Working virtual page is NOT marked as broken');
|
2016-03-08 21:50:55 +01:00
|
|
|
|
2014-08-12 06:39:11 +02:00
|
|
|
$vp->CopyContentFromID = 12345678;
|
2011-03-18 04:23:47 +01:00
|
|
|
$vp->syncLinkTracking();
|
|
|
|
$this->assertTrue($vp->HasBrokenLink, 'Broken virtual page IS marked as such');
|
|
|
|
}
|
2014-08-12 06:39:11 +02:00
|
|
|
|
2012-09-19 12:07:46 +02:00
|
|
|
public function testBrokenInternalRedirectorPages() {
|
2011-03-18 04:23:47 +01:00
|
|
|
$obj = $this->objFromFixture('Page','content');
|
|
|
|
$rp = new RedirectorPage();
|
2016-03-08 21:50:55 +01:00
|
|
|
|
2011-03-18 04:23:47 +01:00
|
|
|
$rp->RedirectionType = 'Internal';
|
2016-03-08 21:50:55 +01:00
|
|
|
|
2014-08-12 06:39:11 +02:00
|
|
|
$rp->LinkToID = $obj->ID;
|
2011-03-18 04:23:47 +01:00
|
|
|
$rp->syncLinkTracking();
|
|
|
|
$this->assertFalse($rp->HasBrokenLink, 'Working redirector page is NOT marked as broken');
|
2016-03-08 21:50:55 +01:00
|
|
|
|
2014-08-12 06:39:11 +02:00
|
|
|
$rp->LinkToID = 12345678;
|
2011-03-18 04:23:47 +01:00
|
|
|
$rp->syncLinkTracking();
|
|
|
|
$this->assertTrue($rp->HasBrokenLink, 'Broken redirector page IS marked as such');
|
|
|
|
}
|
|
|
|
|
2012-09-19 12:07:46 +02:00
|
|
|
public function testDeletingFileMarksBackedPagesAsBroken() {
|
2011-03-18 04:23:47 +01:00
|
|
|
// Test entry
|
|
|
|
$file = new File();
|
2016-01-26 06:38:42 +01:00
|
|
|
$file->setFromString('test', 'test-file.txt');
|
2011-03-18 04:23:47 +01:00
|
|
|
$file->write();
|
|
|
|
|
|
|
|
$obj = $this->objFromFixture('Page','content');
|
2014-04-16 23:05:18 +02:00
|
|
|
$obj->Content = sprintf(
|
|
|
|
'<p><a href="[file_link,id=%d]">Working Link</a></p>',
|
|
|
|
$file->ID
|
|
|
|
);
|
2011-03-18 04:23:47 +01:00
|
|
|
$obj->write();
|
2016-04-01 05:17:37 +02:00
|
|
|
$this->assertTrue($obj->publishRecursive());
|
2011-03-18 04:23:47 +01:00
|
|
|
// Confirm that it isn't marked as broken to begin with
|
|
|
|
$obj->flushCache();
|
|
|
|
$obj = DataObject::get_by_id("SiteTree", $obj->ID);
|
|
|
|
$this->assertEquals(0, $obj->HasBrokenFile);
|
|
|
|
|
|
|
|
$liveObj = Versioned::get_one_by_stage("SiteTree", "Live","\"SiteTree\".\"ID\" = $obj->ID");
|
|
|
|
$this->assertEquals(0, $liveObj->HasBrokenFile);
|
2016-03-08 21:50:55 +01:00
|
|
|
|
2011-03-18 04:23:47 +01:00
|
|
|
// Delete the file
|
|
|
|
$file->delete();
|
|
|
|
|
2016-01-26 06:38:42 +01:00
|
|
|
// Confirm that it is marked as broken in stage
|
2011-03-18 04:23:47 +01:00
|
|
|
$obj->flushCache();
|
|
|
|
$obj = DataObject::get_by_id("SiteTree", $obj->ID);
|
|
|
|
$this->assertEquals(1, $obj->HasBrokenFile);
|
|
|
|
|
2016-01-26 06:38:42 +01:00
|
|
|
// Publishing this page marks it as broken on live too
|
2016-04-01 05:17:37 +02:00
|
|
|
$obj->publishRecursive();
|
2011-03-18 04:23:47 +01:00
|
|
|
$liveObj = Versioned::get_one_by_stage("SiteTree", "Live", "\"SiteTree\".\"ID\" = $obj->ID");
|
|
|
|
$this->assertEquals(1, $liveObj->HasBrokenFile);
|
2014-08-12 06:39:11 +02:00
|
|
|
}
|
|
|
|
|
2012-09-19 12:07:46 +02:00
|
|
|
public function testDeletingMarksBackLinkedPagesAsBroken() {
|
2011-03-18 04:23:47 +01:00
|
|
|
// Set up two published pages with a link from content -> about
|
|
|
|
$linkDest = $this->objFromFixture('Page','about');
|
2016-03-08 21:50:55 +01:00
|
|
|
|
2011-03-18 04:23:47 +01:00
|
|
|
$linkSrc = $this->objFromFixture('Page','content');
|
2012-07-12 04:51:19 +02:00
|
|
|
$linkSrc->Content = "<p><a href=\"[sitetree_link,id=$linkDest->ID]\">about us</a></p>";
|
2011-03-18 04:23:47 +01:00
|
|
|
$linkSrc->write();
|
2016-03-08 21:50:55 +01:00
|
|
|
|
2011-03-18 04:23:47 +01:00
|
|
|
// Confirm no broken link
|
|
|
|
$this->assertEquals(0, (int)$linkSrc->HasBrokenLink);
|
2016-03-08 21:50:55 +01:00
|
|
|
|
2011-03-18 04:23:47 +01:00
|
|
|
// Delete page from draft
|
|
|
|
$linkDestID = $linkDest->ID;
|
|
|
|
$linkDest->delete();
|
|
|
|
|
2016-01-26 06:38:42 +01:00
|
|
|
// Confirm draft has broken link
|
2011-03-18 04:23:47 +01:00
|
|
|
$linkSrc->flushCache();
|
|
|
|
$linkSrc = $this->objFromFixture('Page', 'content');
|
|
|
|
|
|
|
|
$this->assertEquals(1, (int)$linkSrc->HasBrokenLink);
|
|
|
|
}
|
|
|
|
|
2012-09-19 12:07:46 +02:00
|
|
|
public function testPublishingSourceBeforeDestHasBrokenLink() {
|
2016-01-26 06:38:42 +01:00
|
|
|
$this->markTestSkipped("Test disabled until versioned many_many implemented");
|
|
|
|
|
2011-03-18 04:23:47 +01:00
|
|
|
$this->logInWithPermission('ADMIN');
|
2016-03-08 21:50:55 +01:00
|
|
|
|
2011-03-18 04:23:47 +01:00
|
|
|
// Set up two draft pages with a link from content -> about
|
|
|
|
$linkDest = $this->objFromFixture('Page','about');
|
|
|
|
// Ensure that it's not on the published site
|
2016-01-26 06:38:42 +01:00
|
|
|
$linkDest->doUnpublish();
|
2016-03-08 21:50:55 +01:00
|
|
|
|
2011-03-18 04:23:47 +01:00
|
|
|
$linkSrc = $this->objFromFixture('Page','content');
|
2012-07-12 04:51:19 +02:00
|
|
|
$linkSrc->Content = "<p><a href=\"[sitetree_link,id=$linkDest->ID]\">about us</a></p>";
|
2011-03-18 04:23:47 +01:00
|
|
|
$linkSrc->write();
|
2016-03-08 21:50:55 +01:00
|
|
|
|
2016-01-06 00:42:07 +01:00
|
|
|
// Publish the source of the link, while the dest is still unpublished.
|
2016-04-01 05:17:37 +02:00
|
|
|
$linkSrc->publishRecursive();
|
2016-03-08 21:50:55 +01:00
|
|
|
|
2011-03-18 04:23:47 +01:00
|
|
|
// Verify that the link isn't broken on draft but is broken on published
|
|
|
|
$this->assertEquals(0, (int)$linkSrc->HasBrokenLink);
|
2016-01-06 00:42:07 +01:00
|
|
|
$this->assertEquals(1, DB::query("SELECT \"HasBrokenLink\" FROM \"SiteTree_Live\"
|
2011-03-18 04:23:47 +01:00
|
|
|
WHERE \"ID\" = $linkSrc->ID")->value());
|
|
|
|
}
|
|
|
|
|
2012-09-19 12:07:46 +02:00
|
|
|
public function testRestoreFixesBrokenLinks() {
|
2016-01-26 06:38:42 +01:00
|
|
|
$this->markTestSkipped("Test disabled until versioned many_many implemented");
|
2013-08-23 04:33:36 +02:00
|
|
|
// Create page and virtual page
|
2011-03-18 04:23:47 +01:00
|
|
|
$p = new Page();
|
|
|
|
$p->Title = "source";
|
|
|
|
$p->write();
|
|
|
|
$pageID = $p->ID;
|
2016-04-01 05:17:37 +02:00
|
|
|
$this->assertTrue($p->publishRecursive());
|
2011-03-18 04:23:47 +01:00
|
|
|
|
|
|
|
// Content links are one kind of link to pages
|
|
|
|
$p2 = new Page();
|
|
|
|
$p2->Title = "regular link";
|
2012-07-12 04:51:19 +02:00
|
|
|
$p2->Content = "<a href=\"[sitetree_link,id=$p->ID]\">test</a>";
|
2011-03-18 04:23:47 +01:00
|
|
|
$p2->write();
|
2016-04-01 05:17:37 +02:00
|
|
|
$this->assertTrue($p2->publishRecursive());
|
2011-03-18 04:23:47 +01:00
|
|
|
|
|
|
|
// Virtual pages are another
|
|
|
|
$vp = new VirtualPage();
|
|
|
|
$vp->CopyContentFromID = $p->ID;
|
|
|
|
$vp->write();
|
|
|
|
|
|
|
|
// Redirector links are a third
|
|
|
|
$rp = new RedirectorPage();
|
|
|
|
$rp->Title = "redirector";
|
|
|
|
$rp->LinkType = 'Internal';
|
|
|
|
$rp->LinkToID = $p->ID;
|
|
|
|
$rp->write();
|
2016-04-01 05:17:37 +02:00
|
|
|
$this->assertTrue($rp->publishRecursive());
|
2011-03-18 04:23:47 +01:00
|
|
|
|
|
|
|
// Confirm that there are no broken links to begin with
|
|
|
|
$this->assertFalse($p2->HasBrokenLink);
|
|
|
|
$this->assertFalse($vp->HasBrokenLink);
|
|
|
|
$this->assertFalse($rp->HasBrokenLink);
|
|
|
|
|
|
|
|
// Unpublish the source page, confirm that the page 2 and RP has a broken link on published
|
|
|
|
$p->doUnpublish();
|
|
|
|
$p2Live = Versioned::get_one_by_stage('SiteTree', 'Live', '"SiteTree"."ID" = ' . $p2->ID);
|
|
|
|
$rpLive = Versioned::get_one_by_stage('SiteTree', 'Live', '"SiteTree"."ID" = ' . $rp->ID);
|
|
|
|
$this->assertEquals(1, $p2Live->HasBrokenLink);
|
|
|
|
$this->assertEquals(1, $rpLive->HasBrokenLink);
|
|
|
|
|
|
|
|
// Delete the source page, confirm that the VP, RP and page 2 have broken links on draft
|
|
|
|
$p->delete();
|
|
|
|
$vp->flushCache();
|
|
|
|
$vp = DataObject::get_by_id('SiteTree', $vp->ID);
|
|
|
|
$p2->flushCache();
|
|
|
|
$p2 = DataObject::get_by_id('SiteTree', $p2->ID);
|
|
|
|
$rp->flushCache();
|
|
|
|
$rp = DataObject::get_by_id('SiteTree', $rp->ID);
|
|
|
|
$this->assertEquals(1, $p2->HasBrokenLink);
|
|
|
|
$this->assertEquals(1, $vp->HasBrokenLink);
|
|
|
|
$this->assertEquals(1, $rp->HasBrokenLink);
|
|
|
|
|
|
|
|
// Restore the page to stage, confirm that this fixes the links
|
|
|
|
$p = Versioned::get_latest_version('SiteTree', $pageID);
|
|
|
|
$p->doRestoreToStage();
|
|
|
|
|
|
|
|
$p2->flushCache();
|
|
|
|
$p2 = DataObject::get_by_id('SiteTree', $p2->ID);
|
|
|
|
$vp->flushCache();
|
|
|
|
$vp = DataObject::get_by_id('SiteTree', $vp->ID);
|
|
|
|
$rp->flushCache();
|
|
|
|
$rp = DataObject::get_by_id('SiteTree', $rp->ID);
|
|
|
|
$this->assertFalse((bool)$p2->HasBrokenLink);
|
|
|
|
$this->assertFalse((bool)$vp->HasBrokenLink);
|
|
|
|
$this->assertFalse((bool)$rp->HasBrokenLink);
|
|
|
|
|
|
|
|
// Publish and confirm that the p2 and RP broken links are fixed on published
|
2016-04-01 05:17:37 +02:00
|
|
|
$this->assertTrue($p->publishRecursive());
|
2011-03-18 04:23:47 +01:00
|
|
|
$p2Live = Versioned::get_one_by_stage('SiteTree', 'Live', '"SiteTree"."ID" = ' . $p2->ID);
|
|
|
|
$rpLive = Versioned::get_one_by_stage('SiteTree', 'Live', '"SiteTree"."ID" = ' . $rp->ID);
|
|
|
|
$this->assertFalse((bool)$p2Live->HasBrokenLink);
|
|
|
|
$this->assertFalse((bool)$rpLive->HasBrokenLink);
|
2016-03-08 21:50:55 +01:00
|
|
|
|
2011-03-18 04:23:47 +01:00
|
|
|
}
|
|
|
|
|
2012-09-19 12:07:46 +02:00
|
|
|
public function testRevertToLiveFixesBrokenLinks() {
|
2011-03-18 04:23:47 +01:00
|
|
|
// Create page and virutal page
|
|
|
|
$p = new Page();
|
|
|
|
$p->Title = "source";
|
|
|
|
$p->write();
|
|
|
|
$pageID = $p->ID;
|
2016-04-01 05:17:37 +02:00
|
|
|
$this->assertTrue($p->publishRecursive());
|
2011-03-18 04:23:47 +01:00
|
|
|
|
|
|
|
// Content links are one kind of link to pages
|
|
|
|
$p2 = new Page();
|
|
|
|
$p2->Title = "regular link";
|
2012-07-12 04:51:19 +02:00
|
|
|
$p2->Content = "<a href=\"[sitetree_link,id=$p->ID]\">test</a>";
|
2011-03-18 04:23:47 +01:00
|
|
|
$p2->write();
|
2016-04-01 05:17:37 +02:00
|
|
|
$this->assertTrue($p2->publishRecursive());
|
2011-03-18 04:23:47 +01:00
|
|
|
|
|
|
|
// Virtual pages are another
|
|
|
|
$vp = new VirtualPage();
|
|
|
|
$vp->CopyContentFromID = $p->ID;
|
|
|
|
$vp->write();
|
|
|
|
|
|
|
|
// Redirector links are a third
|
|
|
|
$rp = new RedirectorPage();
|
|
|
|
$rp->Title = "redirector";
|
|
|
|
$rp->LinkType = 'Internal';
|
|
|
|
$rp->LinkToID = $p->ID;
|
|
|
|
$rp->write();
|
2016-04-01 05:17:37 +02:00
|
|
|
$this->assertTrue($rp->publishRecursive());
|
2011-03-18 04:23:47 +01:00
|
|
|
|
|
|
|
// Confirm that there are no broken links to begin with
|
|
|
|
$this->assertFalse($p2->HasBrokenLink);
|
|
|
|
$this->assertFalse($vp->HasBrokenLink);
|
|
|
|
$this->assertFalse($rp->HasBrokenLink);
|
|
|
|
|
|
|
|
// Delete from draft and confirm that broken links are marked
|
|
|
|
$pID = $p->ID;
|
|
|
|
$p->delete();
|
2016-03-08 21:50:55 +01:00
|
|
|
|
2011-03-18 04:23:47 +01:00
|
|
|
$vp->flushCache();
|
|
|
|
$vp = DataObject::get_by_id('SiteTree', $vp->ID);
|
|
|
|
$p2->flushCache();
|
|
|
|
$p2 = DataObject::get_by_id('SiteTree', $p2->ID);
|
|
|
|
$rp->flushCache();
|
|
|
|
$rp = DataObject::get_by_id('SiteTree', $rp->ID);
|
|
|
|
$this->assertEquals(1, $p2->HasBrokenLink);
|
|
|
|
$this->assertEquals(1, $vp->HasBrokenLink);
|
|
|
|
$this->assertEquals(1, $rp->HasBrokenLink);
|
|
|
|
|
|
|
|
// Call doRevertToLive and confirm that broken links are restored
|
|
|
|
$pLive = Versioned::get_one_by_stage('SiteTree', 'Live', '"SiteTree"."ID" = ' . $pID);
|
|
|
|
$pLive->doRevertToLive();
|
|
|
|
|
|
|
|
$p2->flushCache();
|
|
|
|
$p2 = DataObject::get_by_id('SiteTree', $p2->ID);
|
|
|
|
$vp->flushCache();
|
|
|
|
$vp = DataObject::get_by_id('SiteTree', $vp->ID);
|
|
|
|
$rp->flushCache();
|
|
|
|
$rp = DataObject::get_by_id('SiteTree', $rp->ID);
|
|
|
|
$this->assertFalse((bool)$p2->HasBrokenLink);
|
|
|
|
$this->assertFalse((bool)$vp->HasBrokenLink);
|
|
|
|
$this->assertFalse((bool)$rp->HasBrokenLink);
|
|
|
|
|
|
|
|
}
|
2013-08-23 04:33:36 +02:00
|
|
|
|
|
|
|
public function testBrokenAnchorLinksInAPage() {
|
|
|
|
$obj = $this->objFromFixture('Page','content');
|
|
|
|
$origContent = $obj->Content;
|
|
|
|
|
|
|
|
$obj->Content = $origContent . '<a href="#no-anchor-here">this links to a non-existent in-page anchor or skiplink</a>';
|
|
|
|
$obj->syncLinkTracking();
|
|
|
|
$this->assertTrue($obj->HasBrokenLink, 'Page has a broken anchor/skiplink');
|
|
|
|
|
|
|
|
$obj->Content = $origContent . '<a href="#yes-anchor-here">this links to an existent in-page anchor/skiplink</a>';
|
|
|
|
$obj->syncLinkTracking();
|
|
|
|
$this->assertFalse($obj->HasBrokenLink, 'Page doesn\'t have a broken anchor or skiplink');
|
|
|
|
}
|
2014-08-12 06:39:11 +02:00
|
|
|
|
2011-03-18 04:23:47 +01:00
|
|
|
}
|
|
|
|
|