mirror of
https://github.com/silverstripe/silverstripe-framework
synced 2024-10-22 14:05:37 +02:00
#63 - Stable against restructures (from r84861)
git-svn-id: svn://svn.silverstripe.com/silverstripe/open/modules/sapphire/trunk@89155 467b73ca-7a2a-4603-9d3b-597d59a354a9
This commit is contained in:
parent
7277ada137
commit
4ab8055c29
@ -1300,9 +1300,50 @@ class SiteTree extends DataObject implements PermissionProvider,i18nEntityProvid
|
|||||||
|
|
||||||
DataObject::set_context_obj(null);
|
DataObject::set_context_obj(null);
|
||||||
|
|
||||||
|
$this->syncLinkTracking();
|
||||||
|
|
||||||
parent::onBeforeWrite();
|
parent::onBeforeWrite();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function syncLinkTracking() {
|
||||||
|
// Set LinkTracking appropriately
|
||||||
|
$links = HTTP::getLinksIn($this->Content);
|
||||||
|
$linkedPages = array();
|
||||||
|
$linkedFiles = array();
|
||||||
|
$this->HasBrokenLink = false;
|
||||||
|
$this->HasBrokenFile = false;
|
||||||
|
|
||||||
|
if($links) foreach($links as $link) {
|
||||||
|
if(preg_match('/^([A-Za-z0-9_-]+)\/?(#.*)?$/', $link, $parts)) {
|
||||||
|
$candidatePage = DataObject::get_one("SiteTree", "\"URLSegment\" = '" . urldecode( $parts[1] ). "'", false);
|
||||||
|
if($candidatePage) {
|
||||||
|
$linkedPages[] = $candidatePage->ID;
|
||||||
|
} else {
|
||||||
|
$this->HasBrokenLink = true;
|
||||||
|
}
|
||||||
|
} else if($link == '' || $link[0] == '/') {
|
||||||
|
$this->HasBrokenLink = true;
|
||||||
|
} else if($candidateFile = DataObject::get_one("File", "\"Filename\" = '" . Convert::raw2sql(urldecode($link)) . "'", false)) {
|
||||||
|
$linkedFiles[] = $candidateFile->ID;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$images = HTTP::getImagesIn($this->Content);
|
||||||
|
if($images) {
|
||||||
|
foreach($images as $image) {
|
||||||
|
$image = Director::makeRelative($image);
|
||||||
|
if(substr($image,0,7) == 'assets/') {
|
||||||
|
$candidateImage = DataObject::get_one("File", "\"Filename\" = '$image'");
|
||||||
|
if($candidateImage) $linkedFiles[] = $candidateImage->ID;
|
||||||
|
else $this->HasBrokenFile = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->LinkTracking()->setByIDList($linkedPages);
|
||||||
|
$this->ImageTracking()->setByIDList($linkedFiles);
|
||||||
|
}
|
||||||
|
|
||||||
function onAfterWrite() {
|
function onAfterWrite() {
|
||||||
// Need to flush cache to avoid outdated versionnumber references
|
// Need to flush cache to avoid outdated versionnumber references
|
||||||
$this->flushCache();
|
$this->flushCache();
|
||||||
@ -1314,6 +1355,19 @@ class SiteTree extends DataObject implements PermissionProvider,i18nEntityProvid
|
|||||||
$page->write();
|
$page->write();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// If the URLSegment has been changed, rewrite links
|
||||||
|
if($this->isChanged('URLSegment', 2)) {
|
||||||
|
if($this->hasMethod('BackLinkTracking')) {
|
||||||
|
$links = $this->BackLinkTracking();
|
||||||
|
if($links) {
|
||||||
|
foreach($links as $link) {
|
||||||
|
$link->rewriteLink($this->original['URLSegment'] . '/', $this->URLSegment . '/');
|
||||||
|
$link->write();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
parent::onAfterWrite();
|
parent::onAfterWrite();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1739,12 +1793,12 @@ class SiteTree extends DataObject implements PermissionProvider,i18nEntityProvid
|
|||||||
|
|
||||||
// Handle activities undertaken by decorators
|
// Handle activities undertaken by decorators
|
||||||
$this->extend('onBeforePublish', $original);
|
$this->extend('onBeforePublish', $original);
|
||||||
|
|
||||||
$this->Status = "Published";
|
$this->Status = "Published";
|
||||||
//$this->PublishedByID = Member::currentUser()->ID;
|
//$this->PublishedByID = Member::currentUser()->ID;
|
||||||
$this->write();
|
$this->write();
|
||||||
$this->publish("Stage", "Live");
|
$this->publish("Stage", "Live");
|
||||||
|
|
||||||
|
|
||||||
if(DB::getConn() instanceof MySQLDatabase) {
|
if(DB::getConn() instanceof MySQLDatabase) {
|
||||||
// Special syntax for MySQL (grr!)
|
// Special syntax for MySQL (grr!)
|
||||||
// More ANSI-compliant syntax
|
// More ANSI-compliant syntax
|
||||||
@ -1769,6 +1823,31 @@ class SiteTree extends DataObject implements PermissionProvider,i18nEntityProvid
|
|||||||
$page->doPublish();
|
$page->doPublish();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Fix links that are different on staging vs live
|
||||||
|
$needsWriting = false;
|
||||||
|
$this->syncLinkTracking();
|
||||||
|
foreach($this->LinkTracking() as $linkedPage) {
|
||||||
|
$livePage = Versioned::get_one_by_stage('Page', 'Live', '"SiteTree"."ID" = ' . $linkedPage->ID);
|
||||||
|
if($livePage && $livePage->URLSegment != $linkedPage->URLSegment) {
|
||||||
|
|
||||||
|
$needsWriting = true;
|
||||||
|
$this->rewriteLink($linkedPage->URLSegment . '/', $livePage->URLSegment . '/');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if($needsWriting) {
|
||||||
|
$this->writeToStage('Live');
|
||||||
|
}
|
||||||
|
|
||||||
|
// If this url has changed, then we need to fix pages linked to this one
|
||||||
|
if($original->URLSegment && $original->URLSegment != $this->URLSegment) {
|
||||||
|
foreach($this->BackLinkTracking() as $linkedPage) {
|
||||||
|
$linkedPageLive = Versioned::get_one_by_stage('Page', 'Live', '"SiteTree"."ID" = ' . $linkedPage->ID);
|
||||||
|
$linkedPageLive->rewriteLink($original->URLSegment . '/', $this->URLSegment . '/');
|
||||||
|
$linkedPageLive->writeToStage('Live');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// Handle activities undertaken by decorators
|
// Handle activities undertaken by decorators
|
||||||
$this->extend('onAfterPublish', $original);
|
$this->extend('onAfterPublish', $original);
|
||||||
}
|
}
|
||||||
|
@ -141,6 +141,7 @@ class HtmlEditorField extends TextareaField {
|
|||||||
if($record->ID && $record->many_many('ImageTracking') && $tracker = $record->ImageTracking()) {
|
if($record->ID && $record->many_many('ImageTracking') && $tracker = $record->ImageTracking()) {
|
||||||
$tracker->removeByFilter(sprintf('"FieldName" = \'%s\' AND "SiteTreeID" = %d', $this->name, $record->ID));
|
$tracker->removeByFilter(sprintf('"FieldName" = \'%s\' AND "SiteTreeID" = %d', $this->name, $record->ID));
|
||||||
|
|
||||||
|
$fieldName = $this->name;
|
||||||
if($linkedFiles) foreach($linkedFiles as $item) {
|
if($linkedFiles) foreach($linkedFiles as $item) {
|
||||||
$tracker->add($item, array('FieldName' => $this->name));
|
$tracker->add($item, array('FieldName' => $this->name));
|
||||||
}
|
}
|
||||||
|
172
tests/SiteTreeBacklinksTest.php
Normal file
172
tests/SiteTreeBacklinksTest.php
Normal file
@ -0,0 +1,172 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
class SiteTreeBacklinksTest extends SapphireTest {
|
||||||
|
static $fixture_file = "sapphire/tests/SiteTreeBacklinksTest.yml";
|
||||||
|
|
||||||
|
function testSavingPageWithLinkAddsBacklink() {
|
||||||
|
// load page 1
|
||||||
|
$page1 = $this->objFromFixture('Page', 'page1');
|
||||||
|
|
||||||
|
// assert backlink to page 2 doesn't exist
|
||||||
|
$page2 = $this->objFromFixture('Page', 'page2');
|
||||||
|
$this->assertFalse($page1->BackLinkTracking()->containsIDs(array($page2->ID)), 'Assert backlink to page 2 doesn\'t exist');
|
||||||
|
|
||||||
|
// add hyperlink to page 1 on page 2
|
||||||
|
$page2->Content .= '<p><a href="page1/">Testing page 1 link</a></p>';
|
||||||
|
$page2->write();
|
||||||
|
|
||||||
|
// load page 1
|
||||||
|
$page1 = $this->objFromFixture('Page', 'page1');
|
||||||
|
|
||||||
|
// assert backlink to page 2 exists
|
||||||
|
$this->assertTrue($page1->BackLinkTracking()->containsIDs(array($page2->ID)), 'Assert backlink to page 2 exists');
|
||||||
|
}
|
||||||
|
|
||||||
|
function testRemovingLinkFromPageRemovesBacklink() {
|
||||||
|
// load page 1
|
||||||
|
$page1 = $this->objFromFixture('Page', 'page1');
|
||||||
|
|
||||||
|
// assert backlink to page 3 exits
|
||||||
|
$page3 = $this->objFromFixture('Page', 'page3');
|
||||||
|
$this->assertTrue($page1->BackLinkTracking()->containsIDs(array($page3->ID)), 'Assert backlink to page 3 exists');
|
||||||
|
|
||||||
|
// remove hyperlink to page 1
|
||||||
|
$page3->Content = '<p>No links anymore!</p>';
|
||||||
|
$page3->write();
|
||||||
|
|
||||||
|
// load page 1
|
||||||
|
$page1 = $this->objFromFixture('Page', 'page1');
|
||||||
|
|
||||||
|
// assert backlink to page 3 exists
|
||||||
|
$this->assertFalse($page1->BackLinkTracking()->containsIDs(array($page3->ID)), 'Assert backlink to page 3 doesn\'t exist');
|
||||||
|
}
|
||||||
|
|
||||||
|
function testChangingUrlOnDraftSiteRewritesLink() {
|
||||||
|
// load page 1
|
||||||
|
$page1 = $this->objFromFixture('Page', 'page1');
|
||||||
|
|
||||||
|
// assert backlink to page 3 exists
|
||||||
|
$page3 = $this->objFromFixture('Page', 'page3');
|
||||||
|
$this->assertTrue($page1->BackLinkTracking()->containsIDs(array($page3->ID)), 'Assert backlink to page 3 exists');
|
||||||
|
|
||||||
|
// assert hyperlink to page 1's current url exists on page 3
|
||||||
|
$links = HTTP::getLinksIn($page3->Content);
|
||||||
|
$this->assertContains('page1/', $links, 'Assert hyperlink to page 1\'s current url exists on page 3');
|
||||||
|
|
||||||
|
// change url of page 1
|
||||||
|
$page1->URLSegment = 'new-url-segment';
|
||||||
|
$page1->write();
|
||||||
|
|
||||||
|
// load page 3
|
||||||
|
$page3 = $this->objFromFixture('Page', 'page3');
|
||||||
|
|
||||||
|
// assert hyperlink to page 1's new url exists
|
||||||
|
$links = HTTP::getLinksIn($page3->Content);
|
||||||
|
$this->assertContains('new-url-segment/', $links, 'Assert hyperlink to page 1\'s new url exists on page 3');
|
||||||
|
}
|
||||||
|
|
||||||
|
function testChangingUrlOnLiveSiteRewritesLink() {
|
||||||
|
// publish page 1 & 3
|
||||||
|
$page1 = $this->objFromFixture('Page', 'page1');
|
||||||
|
$page3 = $this->objFromFixture('Page', 'page3');
|
||||||
|
$page1->doPublish();
|
||||||
|
$page3->doPublish();
|
||||||
|
|
||||||
|
// load pages from live
|
||||||
|
$page1live = Versioned::get_one_by_stage('Page', 'Live', '"SiteTree"."ID" = ' . $page1->ID);
|
||||||
|
$page3live = Versioned::get_one_by_stage('Page', 'Live', '"SiteTree"."ID" = ' . $page3->ID);
|
||||||
|
|
||||||
|
// assert backlink to page 3 exists
|
||||||
|
$this->assertTrue($page1live->BackLinkTracking()->containsIDs(array($page3live->ID)), 'Assert backlink to page 3 exists');
|
||||||
|
|
||||||
|
// assert hyperlink to page 1's current url exists on page 3
|
||||||
|
$links = HTTP::getLinksIn($page3live->Content);
|
||||||
|
$this->assertContains('page1/', $links, 'Assert hyperlink to page 1\'s current url exists on page 3');
|
||||||
|
|
||||||
|
// change url of page 1
|
||||||
|
$page1live->URLSegment = 'new-url-segment';
|
||||||
|
$page1live->writeToStage('Live');
|
||||||
|
|
||||||
|
// load page 3 from live
|
||||||
|
$page3live = Versioned::get_one_by_stage('Page', 'Live', '"SiteTree"."ID" = ' . $page3->ID);
|
||||||
|
|
||||||
|
// assert hyperlink to page 1's new url exists
|
||||||
|
$links = HTTP::getLinksIn($page3live->Content);
|
||||||
|
$this->assertContains('new-url-segment/', $links, 'Assert hyperlink to page 1\'s new url exists on page 3');
|
||||||
|
}
|
||||||
|
|
||||||
|
function testPublishingPageWithModifiedUrlRewritesLink() {
|
||||||
|
// publish page 1 & 3
|
||||||
|
$page1 = $this->objFromFixture('Page', 'page1');
|
||||||
|
$page3 = $this->objFromFixture('Page', 'page3');
|
||||||
|
|
||||||
|
$page1->doPublish();
|
||||||
|
$page3->doPublish();
|
||||||
|
|
||||||
|
// load page 3 from live
|
||||||
|
$page3live = Versioned::get_one_by_stage('Page', 'Live', '"SiteTree"."ID" = ' . $page3->ID);
|
||||||
|
|
||||||
|
// assert hyperlink to page 1's current url exists
|
||||||
|
$links = HTTP::getLinksIn($page3live->Content);
|
||||||
|
$this->assertContains('page1/', $links, 'Assert hyperlink to page 1\'s current url exists on page 3');
|
||||||
|
|
||||||
|
// rename url of page 1 on stage
|
||||||
|
$page1->URLSegment = 'new-url-segment';
|
||||||
|
$page1->write();
|
||||||
|
|
||||||
|
// assert hyperlink to page 1's current publish url exists
|
||||||
|
$page3live = Versioned::get_one_by_stage('Page', 'Live', '"SiteTree"."ID" = ' . $page3->ID);
|
||||||
|
$links = HTTP::getLinksIn($page3live->Content);
|
||||||
|
$this->assertContains('page1/', $links, 'Assert hyperlink to page 1\'s current published url exists on page 3');
|
||||||
|
|
||||||
|
|
||||||
|
// publish page 1
|
||||||
|
$page1->doPublish();
|
||||||
|
|
||||||
|
// assert hyperlink to page 1's new published url exists
|
||||||
|
$page3live = Versioned::get_one_by_stage('Page', 'Live', '"SiteTree"."ID" = ' . $page3->ID);
|
||||||
|
$links = HTTP::getLinksIn($page3live->Content);
|
||||||
|
$this->assertContains('new-url-segment/', $links, 'Assert hyperlink to page 1\'s new published url exists on page 3');
|
||||||
|
}
|
||||||
|
|
||||||
|
function testPublishingPageWithModifiedLinksRewritesLinks() {
|
||||||
|
// publish page 1 & 3
|
||||||
|
$page1 = $this->objFromFixture('Page', 'page1');
|
||||||
|
$page3 = $this->objFromFixture('Page', 'page3');
|
||||||
|
$page1->doPublish();
|
||||||
|
$page3->doPublish();
|
||||||
|
|
||||||
|
// assert hyperlink to page 1's current url exists
|
||||||
|
$links = HTTP::getLinksIn($page3->Content);
|
||||||
|
$this->assertContains('page1/', $links, 'Assert hyperlink to page 1\'s current published url exists on page 3');
|
||||||
|
|
||||||
|
// change page 1 url on draft
|
||||||
|
$page1->URLSegment = 'new-url-segment';
|
||||||
|
|
||||||
|
// save page 1
|
||||||
|
$page1->write();
|
||||||
|
|
||||||
|
// assert page 3 on draft contains new page 1 url
|
||||||
|
$page3 = $this->objFromFixture('Page', 'page3');
|
||||||
|
$links = HTTP::getLinksIn($page3->Content);
|
||||||
|
$this->assertContains('new-url-segment/', $links, 'Assert hyperlink to page 1\'s current draft url exists on page 3');
|
||||||
|
|
||||||
|
// publish page 3
|
||||||
|
$page3->doPublish();
|
||||||
|
|
||||||
|
// assert page 3 on published site contains old page 1 url
|
||||||
|
$page3live = Versioned::get_one_by_stage('Page', 'Live', '"SiteTree"."ID" = ' . $page3->ID);
|
||||||
|
$links = HTTP::getLinksIn($page3live->Content);
|
||||||
|
$this->assertContains('page1/', $links, 'Assert hyperlink to page 1\'s current published url exists on page 3');
|
||||||
|
|
||||||
|
// publish page 1
|
||||||
|
$page1->doPublish();
|
||||||
|
|
||||||
|
// assert page 3 on published site contains new page 1 url
|
||||||
|
$page3live = Versioned::get_one_by_stage('Page', 'Live', '"SiteTree"."ID" = ' . $page3->ID);
|
||||||
|
$links = HTTP::getLinksIn($page3live->Content);
|
||||||
|
$this->assertContains('new-url-segment/', $links, 'Assert hyperlink to page 1\'s current published url exists on page 3');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
?>
|
16
tests/SiteTreeBacklinksTest.yml
Normal file
16
tests/SiteTreeBacklinksTest.yml
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
Page:
|
||||||
|
page1:
|
||||||
|
Title: page1
|
||||||
|
URLSegment: page1
|
||||||
|
|
||||||
|
page2:
|
||||||
|
Title: page2
|
||||||
|
URLSegment: page2
|
||||||
|
|
||||||
|
page3:
|
||||||
|
Title: page3
|
||||||
|
URLSegment: page3
|
||||||
|
Content: <p><a href="page1/">Testing page 1 link</a></p>
|
||||||
|
LinkTracking: =>Page.page1
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user