Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

NEW Track broken links and files within ElementContent #861

Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 11 additions & 1 deletion src/Extensions/ElementalAreasExtension.php
Original file line number Diff line number Diff line change
Expand Up @@ -229,13 +229,23 @@ public function onBeforeWrite()

$ownerClassName = get_class($this->owner);

// Update the OwnerClassName on EA if the class has changed
foreach ($elementalAreaRelations as $eaRelation) {
// Update the OwnerClassName on EA if the class has changed
/** @var ElementalArea $ea */
$ea = $this->owner->$eaRelation();
if ($ea->OwnerClassName !== $ownerClassName) {
$ea->OwnerClassName = $ownerClassName;
$ea->write();
}

// Owner page will have set its own HasBrokenLink / HasBrokenFile in SiteTreeLinkTracking / FileLinkTracking
// on any $page->Content BEFORE we get to this point
if (in_array(1, $ea->Elements()->column('HasBrokenLink'))) {
$this->owner->HasBrokenLink = true;
}
if (in_array(1, $ea->Elements()->column('HasBrokenFile'))) {
$this->owner->HasBrokenFile = true;
}
}

if (Config::inst()->get(self::class, 'clear_contentfield')) {
Expand Down
41 changes: 40 additions & 1 deletion src/Models/BaseElement.php
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
use SilverStripe\ORM\FieldType\DBBoolean;
use SilverStripe\ORM\FieldType\DBField;
use SilverStripe\ORM\FieldType\DBHTMLText;
use SilverStripe\ORM\Queries\SQLUpdate;
use SilverStripe\ORM\ValidationException;
use SilverStripe\Security\Member;
use SilverStripe\Security\Permission;
Expand Down Expand Up @@ -70,7 +71,9 @@ class BaseElement extends DataObject
'ShowTitle' => 'Boolean',
'Sort' => 'Int',
'ExtraClass' => 'Varchar(255)',
'Style' => 'Varchar(255)'
'Style' => 'Varchar(255)',
'HasBrokenLink' => 'Boolean',
'HasBrokenFile' => 'Boolean',
];

private static $has_one = [
Expand Down Expand Up @@ -280,6 +283,39 @@ public function onBeforeWrite()

$this->Sort = $records->max('Sort') + 1;
}
$this->updatePageHasBrokenItems();
}

public function onBeforePublish()
{
$this->updatePageHasBrokenItems('live');
}

private function updatePageHasBrokenItems($stage = 'Stage')
{
// Update Page HasBrokenLink/HasBrokenFile so that broken links report stays up-to-date
// Bypass ORM to prevent any side-effects
$page = $this->getPage();
if ($page && $page->exists()) {
$assignments = [];
if (!$page->HasBrokenLink && $this->HasBrokenLink) {
$assignments['"HasBrokenLink"'] = true;
}
if (!$page->HasBrokenFile && $this->HasBrokenFile) {
$assignments['"HasBrokenFile"'] = true;
}
if (!empty($assignments)) {
$tableName = DataObject::getSchema()->tableName(SiteTree::class);
if (strtolower($stage == 'live')) {
$tableName .= '_Live';
}
SQLUpdate::create()
->setTable($tableName)
->setAssignments($assignments)
->setWhere('"ID"', $page->ID)
->execute();
}
}
}

public function getCMSFields()
Expand All @@ -292,6 +328,9 @@ public function getCMSFields()
// Remove link and file tracking tabs
$fields->removeByName(['LinkTracking', 'FileTracking']);

// Remove SiteTreeLinkTracking and FileLinkTracking fields
$fields->removeByName(['HasBrokenLink', 'HasBrokenFile']);

$fields->addFieldToTab(
'Root.Settings',
TextField::create('ExtraClass', _t(__CLASS__ . '.ExtraCssClassesLabel', 'Custom CSS classes'))
Expand Down
2 changes: 1 addition & 1 deletion src/Models/ElementContent.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ class ElementContent extends BaseElement
private static $icon = 'font-icon-block-content';

private static $db = [
'HTML' => 'HTMLText'
'HTML' => 'HTMLText',
];

private static $table_name = 'ElementContent';
Expand Down
107 changes: 106 additions & 1 deletion tests/Extensions/ElementalAreasExtensionTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,11 @@
namespace DNADesign\Elemental\Tests\Extensions;

use DNADesign\Elemental\Extensions\ElementalAreasExtension;
use DNADesign\Elemental\Extensions\ElementalPageExtension;
use DNADesign\Elemental\Models\ElementContent;
use DNADesign\Elemental\Tests\Src\TestElement;
use DNADesign\Elemental\Tests\Src\TestUnusedElement;
use SilverStripe\Assets\File;
use SilverStripe\Core\Config\Config;
use SilverStripe\CMS\Model\SiteTree;
use SilverStripe\Dev\SapphireTest;
Expand All @@ -14,9 +16,12 @@

class ElementalAreasExtensionTest extends SapphireTest
{

protected $usesDatabase = true;

protected static $required_extensions = [
SiteTree::class => [
ElementalAreasExtension::class,
ElementalPageExtension::class,
],
];

Expand Down Expand Up @@ -110,4 +115,104 @@ public function provideContentFieldPreservationSettings()
[true, true, HTMLEditorField::class],
];
}

private function setupBrokenData($type)
{
$linkedToPage = SiteTree::create();
$linkedToPage->write();

$linkedToFile = File::create();
$linkedToFile->write();

$id = $type == 'links' ? $linkedToPage->ID : $linkedToFile->ID;
$shortcode = $type == 'links' ? 'sitetree_link' : 'file_link';
// class="ss-broken"
$broken = '<p>Lorem <a href="[' . $shortcode . ',id=99999]">internal broken ' . $type . '</a> ip</p>';
$unbroken = '<p>Lorem <a href="[' . $shortcode . ',id='. $id .']">internal ' . $type . '</a> ip</p>';

$page = SiteTree::create();
$page->Content = $unbroken;
$page->write();

$elementalArea = $page->ElementalArea();
$element = ElementContent::create();
$element->HTML = $unbroken;
$element->ParentID = $elementalArea->ID;
$element->write();

$page->write();
$this->assertFalse($page->HasBrokenLink);
$this->assertFalse($page->HasBrokenFile);

return [
'page' => $page,
'element' => $element,
'broken' => $broken,
'unbroken' => $unbroken
];
}

/**
* Saving the page updates SiteTree->HasBroken from grandchild ElementContent->HasBrokenLink|HasBrokenFile
*/
public function testHasBrokenSavingPage()
{
foreach (['links' => 'HasBrokenLink', 'files' => 'HasBrokenFile'] as $type => $field) {
list('page' => $page, 'element' => $element, 'broken' => $broken) = $this->setupBrokenData($type);
$element->HTML = $broken;
$element->write();
$page->write();
$this->assertTrue($page->$field);
}
}

/**
* Saving the element does not update grandparent SiteTree->HasBrokenLink|HasBrokenFile
*/
public function testHasBrokenSavingElementDoesNotUpdatePage()
{
foreach (['links' => 'HasBrokenLink', 'files' => 'HasBrokenFile'] as $type => $field) {
list('page' => $page, 'element' => $element, 'broken' => $broken) = $this->setupBrokenData($type);
$element->HTML = $broken;
$element->write();
$this->assertFalse($page->$field);
}
}

/**
* Fixing a broken element link sets SiteTree->HasBrokenLink|HasBrokenFile to false
*/
public function testHasBrokenFixSetsSiteTreeToFalse()
{
foreach (['links' => 'HasBrokenLink', 'files' => 'HasBrokenFile'] as $type => $field) {
list('page' => $page, 'element' => $element, 'broken' => $broken, 'unbroken' => $unbroken)
= $this->setupBrokenData($type);
$element->HTML = $broken;
$element->write();
$page->write();
$this->assertTrue($page->$field);
$element->HTML = $unbroken;
$element->write();
$page->write();
$this->assertFalse($page->$field);
}
}

/**
* Unbroken element links do not overwrite SiteTree->HasBrokenLink|HasBrokenFile
*/
public function testHasBrokenUnbrokenDoesNotOverwriteBrokenSiteTree()
{
foreach (['links' => 'HasBrokenLink', 'files' => 'HasBrokenFile'] as $type => $field) {
list('page' => $page, 'element' => $element, 'broken' => $broken, 'unbroken' => $unbroken)
= $this->setupBrokenData($type);
$page->Content = $broken;
$page->write();
$this->assertTrue($page->$field);
$element->HTML = $unbroken;
$element->write();
$page->write();
$this->assertTrue($page->$field);
}
}
}