mirror of
https://github.com/silverstripe/silverstripe-reports
synced 2024-10-22 09:05:53 +00:00
FIX Add SiteTree link tracking as an extension, and apply to SiteTree itself
This commit is contained in:
parent
8ad00a1004
commit
71608f0d4a
@ -163,6 +163,7 @@ class SiteTree extends DataObject implements PermissionProvider,i18nEntityProvid
|
|||||||
private static $extensions = array(
|
private static $extensions = array(
|
||||||
"Hierarchy",
|
"Hierarchy",
|
||||||
"Versioned('Stage', 'Live')",
|
"Versioned('Stage', 'Live')",
|
||||||
|
"SiteTreeLinkTracking"
|
||||||
);
|
);
|
||||||
|
|
||||||
private static $searchable_fields = array(
|
private static $searchable_fields = array(
|
||||||
@ -1469,28 +1470,6 @@ class SiteTree extends DataObject implements PermissionProvider,i18nEntityProvid
|
|||||||
}
|
}
|
||||||
|
|
||||||
public function syncLinkTracking() {
|
public function syncLinkTracking() {
|
||||||
// Build a list of HTMLText fields
|
|
||||||
$allFields = $this->db();
|
|
||||||
$htmlFields = array();
|
|
||||||
foreach($allFields as $field => $fieldSpec) {
|
|
||||||
if(preg_match('/([^(]+)/', $fieldSpec, $matches)) {
|
|
||||||
$class = $matches[0];
|
|
||||||
if(class_exists($class)){
|
|
||||||
if($class == 'HTMLText' || is_subclass_of($class, 'HTMLText')) $htmlFields[] = $field;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
$linkedPages = array();
|
|
||||||
$linkedFiles = array();
|
|
||||||
$this->HasBrokenLink = false;
|
|
||||||
$this->HasBrokenFile = false;
|
|
||||||
|
|
||||||
foreach($htmlFields as $field) {
|
|
||||||
$formField = new HTMLEditorField($field);
|
|
||||||
$formField->setValue($this->$field);
|
|
||||||
$formField->saveInto($this);
|
|
||||||
}
|
|
||||||
$this->extend('augmentSyncLinkTracking');
|
$this->extend('augmentSyncLinkTracking');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
127
code/model/SiteTreeLinkTracking.php
Normal file
127
code/model/SiteTreeLinkTracking.php
Normal file
@ -0,0 +1,127 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds tracking of links in any HTMLText fields which reference SiteTree or File items
|
||||||
|
*
|
||||||
|
* Attaching this to any DataObject will add four fields which contain all links to SiteTree and File items
|
||||||
|
* referenced in any HTMLText fields, and two booleans to indicate if there are any broken links
|
||||||
|
*
|
||||||
|
* Call augmentSyncLinkTracking to update those fields with any changes to those fields
|
||||||
|
*/
|
||||||
|
class SiteTreeLinkTracking extends DataExtension {
|
||||||
|
|
||||||
|
private static $db = array(
|
||||||
|
"HasBrokenFile" => "Boolean",
|
||||||
|
"HasBrokenLink" => "Boolean"
|
||||||
|
);
|
||||||
|
|
||||||
|
private static $many_many = array(
|
||||||
|
"LinkTracking" => "SiteTree",
|
||||||
|
"ImageTracking" => "File"
|
||||||
|
);
|
||||||
|
|
||||||
|
private static $many_many_extraFields = array(
|
||||||
|
"LinkTracking" => array("FieldName" => "Varchar"),
|
||||||
|
"ImageTracking" => array("FieldName" => "Varchar")
|
||||||
|
);
|
||||||
|
|
||||||
|
function trackLinksInField($field) {
|
||||||
|
$record = $this->owner;
|
||||||
|
|
||||||
|
$linkedPages = array();
|
||||||
|
$linkedFiles = array();
|
||||||
|
|
||||||
|
$htmlValue = Injector::inst()->create('HTMLValue', $record->$field);
|
||||||
|
|
||||||
|
// Populate link tracking for internal links & links to asset files.
|
||||||
|
if($links = $htmlValue->getElementsByTagName('a')) foreach($links as $link) {
|
||||||
|
$href = Director::makeRelative($link->getAttribute('href'));
|
||||||
|
|
||||||
|
if($href) {
|
||||||
|
if(preg_match('/\[sitetree_link,id=([0-9]+)\]/i', $href, $matches)) {
|
||||||
|
$ID = $matches[1];
|
||||||
|
|
||||||
|
// clear out any broken link classes
|
||||||
|
if($class = $link->getAttribute('class')) {
|
||||||
|
$link->setAttribute('class',
|
||||||
|
preg_replace('/(^ss-broken|ss-broken$| ss-broken )/', null, $class));
|
||||||
|
}
|
||||||
|
|
||||||
|
$linkedPages[] = $ID;
|
||||||
|
if(!DataObject::get_by_id('SiteTree', $ID)) $record->HasBrokenLink = true;
|
||||||
|
|
||||||
|
} else if(substr($href, 0, strlen(ASSETS_DIR) + 1) == ASSETS_DIR.'/') {
|
||||||
|
$candidateFile = File::find(Convert::raw2sql(urldecode($href)));
|
||||||
|
if($candidateFile) {
|
||||||
|
$linkedFiles[] = $candidateFile->ID;
|
||||||
|
} else {
|
||||||
|
$record->HasBrokenFile = true;
|
||||||
|
}
|
||||||
|
} else if($href == '' || $href[0] == '/') {
|
||||||
|
$record->HasBrokenLink = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add file tracking for image references
|
||||||
|
if($images = $htmlValue->getElementsByTagName('img')) foreach($images as $img) {
|
||||||
|
if($image = File::find($path = urldecode(Director::makeRelative($img->getAttribute('src'))))) {
|
||||||
|
$linkedFiles[] = $image->ID;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if(substr($path, 0, strlen(ASSETS_DIR) + 1) == ASSETS_DIR . '/') {
|
||||||
|
$record->HasBrokenFile = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update the "LinkTracking" many_many
|
||||||
|
if($record->ID && $record->many_many('LinkTracking') && $tracker = $record->LinkTracking()) {
|
||||||
|
$tracker->removeByFilter(sprintf(
|
||||||
|
'"FieldName" = \'%s\' AND "%s" = %d',
|
||||||
|
$field,
|
||||||
|
$tracker->getForeignKey(),
|
||||||
|
$record->ID
|
||||||
|
));
|
||||||
|
|
||||||
|
if($linkedPages) foreach($linkedPages as $item) {
|
||||||
|
$tracker->add($item, array('FieldName' => $field));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update the "ImageTracking" many_many
|
||||||
|
if($record->ID && $record->many_many('ImageTracking') && $tracker = $record->ImageTracking()) {
|
||||||
|
$tracker->removeByFilter(sprintf(
|
||||||
|
'"FieldName" = \'%s\' AND "%s" = %d',
|
||||||
|
$field,
|
||||||
|
$tracker->getForeignKey(),
|
||||||
|
$record->ID
|
||||||
|
));
|
||||||
|
|
||||||
|
if($linkedFiles) foreach($linkedFiles as $item) {
|
||||||
|
$tracker->add($item, array('FieldName' => $field));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function augmentSyncLinkTracking() {
|
||||||
|
// Reset boolean broken flags
|
||||||
|
$this->owner->HasBrokenLink = false;
|
||||||
|
$this->owner->HasBrokenFile = false;
|
||||||
|
|
||||||
|
// Build a list of HTMLText fields
|
||||||
|
$allFields = $this->owner->db();
|
||||||
|
$htmlFields = array();
|
||||||
|
foreach($allFields as $field => $fieldSpec) {
|
||||||
|
if(preg_match('/([^(]+)/', $fieldSpec, $matches)) {
|
||||||
|
$class = $matches[0];
|
||||||
|
if(class_exists($class)){
|
||||||
|
if($class == 'HTMLText' || is_subclass_of($class, 'HTMLText')) $htmlFields[] = $field;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach($htmlFields as $field) $this->trackLinksInField($field);
|
||||||
|
}
|
||||||
|
}
|
@ -13,12 +13,14 @@ class SiteTreeHtmlEditorFieldTest extends FunctionalTest {
|
|||||||
|
|
||||||
$editor->setValue("<a href=\"[sitetree_link,id=$aboutID]\">Example Link</a>");
|
$editor->setValue("<a href=\"[sitetree_link,id=$aboutID]\">Example Link</a>");
|
||||||
$editor->saveInto($sitetree);
|
$editor->saveInto($sitetree);
|
||||||
|
$sitetree->write();
|
||||||
$this->assertEquals(array($aboutID => $aboutID), $sitetree->LinkTracking()->getIdList(), 'Basic link tracking works.');
|
$this->assertEquals(array($aboutID => $aboutID), $sitetree->LinkTracking()->getIdList(), 'Basic link tracking works.');
|
||||||
|
|
||||||
$editor->setValue (
|
$editor->setValue (
|
||||||
"<a href=\"[sitetree_link,id=$aboutID]\"></a><a href=\"[sitetree_link,id=$contactID]\"></a>"
|
"<a href=\"[sitetree_link,id=$aboutID]\"></a><a href=\"[sitetree_link,id=$contactID]\"></a>"
|
||||||
);
|
);
|
||||||
$editor->saveInto($sitetree);
|
$editor->saveInto($sitetree);
|
||||||
|
$sitetree->write();
|
||||||
$this->assertEquals (
|
$this->assertEquals (
|
||||||
array($aboutID => $aboutID, $contactID => $contactID),
|
array($aboutID => $aboutID, $contactID => $contactID),
|
||||||
$sitetree->LinkTracking()->getIdList(),
|
$sitetree->LinkTracking()->getIdList(),
|
||||||
@ -27,6 +29,7 @@ class SiteTreeHtmlEditorFieldTest extends FunctionalTest {
|
|||||||
|
|
||||||
$editor->setValue(null);
|
$editor->setValue(null);
|
||||||
$editor->saveInto($sitetree);
|
$editor->saveInto($sitetree);
|
||||||
|
$sitetree->write();
|
||||||
$this->assertEquals(array(), $sitetree->LinkTracking()->getIdList(), 'Link tracking is removed when links are.');
|
$this->assertEquals(array(), $sitetree->LinkTracking()->getIdList(), 'Link tracking is removed when links are.');
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -37,12 +40,14 @@ class SiteTreeHtmlEditorFieldTest extends FunctionalTest {
|
|||||||
|
|
||||||
$editor->setValue('<a href="assets/example.pdf">Example File</a>');
|
$editor->setValue('<a href="assets/example.pdf">Example File</a>');
|
||||||
$editor->saveInto($sitetree);
|
$editor->saveInto($sitetree);
|
||||||
|
$sitetree->write();
|
||||||
$this->assertEquals (
|
$this->assertEquals (
|
||||||
array($fileID => $fileID), $sitetree->ImageTracking()->getIDList(), 'Links to assets are tracked.'
|
array($fileID => $fileID), $sitetree->ImageTracking()->getIDList(), 'Links to assets are tracked.'
|
||||||
);
|
);
|
||||||
|
|
||||||
$editor->setValue(null);
|
$editor->setValue(null);
|
||||||
$editor->saveInto($sitetree);
|
$editor->saveInto($sitetree);
|
||||||
|
$sitetree->write();
|
||||||
$this->assertEquals(array(), $sitetree->ImageTracking()->getIdList(), 'Asset tracking is removed with links.');
|
$this->assertEquals(array(), $sitetree->ImageTracking()->getIdList(), 'Asset tracking is removed with links.');
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -52,6 +57,7 @@ class SiteTreeHtmlEditorFieldTest extends FunctionalTest {
|
|||||||
|
|
||||||
$editor->setValue('<img src="assets/example.jpg" />');
|
$editor->setValue('<img src="assets/example.jpg" />');
|
||||||
$editor->saveInto($sitetree);
|
$editor->saveInto($sitetree);
|
||||||
|
$sitetree->write();
|
||||||
|
|
||||||
$parser = new CSSContentParser($sitetree->Content);
|
$parser = new CSSContentParser($sitetree->Content);
|
||||||
$xml = $parser->getByXpath('//img');
|
$xml = $parser->getByXpath('//img');
|
||||||
@ -60,6 +66,7 @@ class SiteTreeHtmlEditorFieldTest extends FunctionalTest {
|
|||||||
|
|
||||||
$editor->setValue('<img src="assets/example.jpg" alt="foo" title="bar" />');
|
$editor->setValue('<img src="assets/example.jpg" alt="foo" title="bar" />');
|
||||||
$editor->saveInto($sitetree);
|
$editor->saveInto($sitetree);
|
||||||
|
$sitetree->write();
|
||||||
|
|
||||||
$parser = new CSSContentParser($sitetree->Content);
|
$parser = new CSSContentParser($sitetree->Content);
|
||||||
$xml = $parser->getByXpath('//img');
|
$xml = $parser->getByXpath('//img');
|
||||||
@ -74,12 +81,14 @@ class SiteTreeHtmlEditorFieldTest extends FunctionalTest {
|
|||||||
|
|
||||||
$editor->setValue('<img src="assets/example.jpg" />');
|
$editor->setValue('<img src="assets/example.jpg" />');
|
||||||
$editor->saveInto($sitetree);
|
$editor->saveInto($sitetree);
|
||||||
|
$sitetree->write();
|
||||||
$this->assertEquals (
|
$this->assertEquals (
|
||||||
array($fileID => $fileID), $sitetree->ImageTracking()->getIDList(), 'Inserted images are tracked.'
|
array($fileID => $fileID), $sitetree->ImageTracking()->getIDList(), 'Inserted images are tracked.'
|
||||||
);
|
);
|
||||||
|
|
||||||
$editor->setValue(null);
|
$editor->setValue(null);
|
||||||
$editor->saveInto($sitetree);
|
$editor->saveInto($sitetree);
|
||||||
|
$sitetree->write();
|
||||||
$this->assertEquals (
|
$this->assertEquals (
|
||||||
array(), $sitetree->ImageTracking()->getIDList(), 'Tracked images are deleted when removed.'
|
array(), $sitetree->ImageTracking()->getIDList(), 'Tracked images are deleted when removed.'
|
||||||
);
|
);
|
||||||
@ -93,6 +102,7 @@ class SiteTreeHtmlEditorFieldTest extends FunctionalTest {
|
|||||||
|
|
||||||
$editor->setValue('<p><a href="[sitetree_link,id=0]">Broken Link</a></p>');
|
$editor->setValue('<p><a href="[sitetree_link,id=0]">Broken Link</a></p>');
|
||||||
$editor->saveInto($sitetree);
|
$editor->saveInto($sitetree);
|
||||||
|
$sitetree->write();
|
||||||
|
|
||||||
$this->assertTrue($sitetree->HasBrokenLink);
|
$this->assertTrue($sitetree->HasBrokenLink);
|
||||||
|
|
||||||
@ -102,6 +112,7 @@ class SiteTreeHtmlEditorFieldTest extends FunctionalTest {
|
|||||||
));
|
));
|
||||||
$sitetree->HasBrokenLink = false;
|
$sitetree->HasBrokenLink = false;
|
||||||
$editor->saveInto($sitetree);
|
$editor->saveInto($sitetree);
|
||||||
|
$sitetree->write();
|
||||||
|
|
||||||
$this->assertFalse((bool) $sitetree->HasBrokenLink);
|
$this->assertFalse((bool) $sitetree->HasBrokenLink);
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user