mirror of
https://github.com/silverstripe/silverstripe-cms
synced 2024-10-22 08:05:56 +02:00
Minor Moved MigrateSiteTreeLinkingTask, RemoveOrphanedPagesTask, UpgradeSiteTreePermissionSchemaTask from /sapphire/tasks/ to cms module /cms/tasks/
This commit is contained in:
parent
5de4f696f3
commit
62de2da9e5
52
tasks/MigrateSiteTreeLinkingTask.php
Executable file
52
tasks/MigrateSiteTreeLinkingTask.php
Executable file
@ -0,0 +1,52 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* Rewrites plain internal HTML links into shortcode form, using existing link tracking information.
|
||||||
|
*
|
||||||
|
* @package cms
|
||||||
|
* @subpackage tasks
|
||||||
|
*/
|
||||||
|
class MigrateSiteTreeLinkingTask extends BuildTask {
|
||||||
|
|
||||||
|
protected $title = 'Migrate SiteTree Linking Task';
|
||||||
|
|
||||||
|
protected $description = 'Rewrites plain internal HTML links into shortcode form, using existing link tracking information.';
|
||||||
|
|
||||||
|
public function run($request) {
|
||||||
|
$pages = 0;
|
||||||
|
$links = 0;
|
||||||
|
|
||||||
|
$linkedPages = DataObject::get(
|
||||||
|
'SiteTree',
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
'INNER JOIN "SiteTree_LinkTracking" ON "SiteTree_LinkTracking"."SiteTreeID" = "SiteTree"."ID"'
|
||||||
|
);
|
||||||
|
|
||||||
|
if($linkedPages) foreach($linkedPages as $page) {
|
||||||
|
$tracking = DB::query(sprintf('SELECT "ChildID", "FieldName" FROM "SiteTree_LinkTracking" WHERE "SiteTreeID" = %d', $page->ID))->map();
|
||||||
|
|
||||||
|
foreach($tracking as $childID => $fieldName) {
|
||||||
|
$linked = DataObject::get_by_id('SiteTree', $childID);
|
||||||
|
|
||||||
|
// TOOD: Replace in all HTMLText fields
|
||||||
|
$page->Content = preg_replace (
|
||||||
|
"/href *= *([\"']?){$linked->URLSegment}\/?/i",
|
||||||
|
"href=$1[sitetree_link id={$linked->ID}]",
|
||||||
|
$page->Content,
|
||||||
|
-1,
|
||||||
|
$replaced
|
||||||
|
);
|
||||||
|
|
||||||
|
if($replaced) {
|
||||||
|
$links += $replaced;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$page->write();
|
||||||
|
$pages++;
|
||||||
|
}
|
||||||
|
|
||||||
|
echo "Rewrote $links link(s) on $pages page(s) to use shortcodes.\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
354
tasks/RemoveOrphanedPagesTask.php
Normal file
354
tasks/RemoveOrphanedPagesTask.php
Normal file
@ -0,0 +1,354 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* Identify "orphaned" pages which point to a parent
|
||||||
|
* that no longer exists in a specific stage.
|
||||||
|
* Shows the pages to an administrator, who can then
|
||||||
|
* decide which pages to remove by ticking a checkbox
|
||||||
|
* and manually executing the removal.
|
||||||
|
*
|
||||||
|
* Caution: Pages also count as orphans if they don't
|
||||||
|
* have parents in this stage, even if the parent has a representation
|
||||||
|
* in the other stage:
|
||||||
|
* - A live child is orphaned if its parent was deleted from live, but still exists on stage
|
||||||
|
* - A stage child is orphaned if its parent was deleted from stage, but still exists on live
|
||||||
|
*
|
||||||
|
* See {@link RemoveOrphanedPagesTaskTest} for an example sitetree
|
||||||
|
* before and after orphan removal.
|
||||||
|
*
|
||||||
|
* @author Ingo Schommer (<firstname>@silverstripe.com), SilverStripe Ltd.
|
||||||
|
*
|
||||||
|
* @package cms
|
||||||
|
* @subpackage tasks
|
||||||
|
*/
|
||||||
|
//class RemoveOrphanedPagesTask extends BuildTask {
|
||||||
|
class RemoveOrphanedPagesTask extends Controller {
|
||||||
|
|
||||||
|
static $allowed_actions = array(
|
||||||
|
'index' => 'ADMIN',
|
||||||
|
'Form' => 'ADMIN',
|
||||||
|
'run' => 'ADMIN',
|
||||||
|
'handleAction' => 'ADMIN',
|
||||||
|
);
|
||||||
|
|
||||||
|
protected $title = 'Removed orphaned pages without existing parents from both stage and live';
|
||||||
|
|
||||||
|
protected $description = "
|
||||||
|
<p>
|
||||||
|
Identify 'orphaned' pages which point to a parent
|
||||||
|
that no longer exists in a specific stage.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
Caution: Pages also count as orphans if they don't
|
||||||
|
have parents in this stage, even if the parent has a representation
|
||||||
|
in the other stage:<br />
|
||||||
|
- A live child is orphaned if its parent was deleted from live, but still exists on stage<br />
|
||||||
|
- A stage child is orphaned if its parent was deleted from stage, but still exists on live
|
||||||
|
</p>
|
||||||
|
";
|
||||||
|
|
||||||
|
protected $orphanedSearchClass = 'SiteTree';
|
||||||
|
|
||||||
|
function Link() {
|
||||||
|
return $this->class;
|
||||||
|
}
|
||||||
|
|
||||||
|
function init() {
|
||||||
|
parent::init();
|
||||||
|
|
||||||
|
if(!Permission::check('ADMIN')) {
|
||||||
|
return Security::permissionFailure($this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function index() {
|
||||||
|
Requirements::javascript(SAPPHIRE_DIR . '/thirdparty/jquery/jquery.js');
|
||||||
|
Requirements::customCSS('#OrphanIDs .middleColumn {width: auto;}');
|
||||||
|
Requirements::customCSS('#OrphanIDs label {display: inline;}');
|
||||||
|
|
||||||
|
return $this->renderWith('BlankPage');
|
||||||
|
}
|
||||||
|
|
||||||
|
function Form() {
|
||||||
|
$fields = new FieldSet();
|
||||||
|
$source = array();
|
||||||
|
|
||||||
|
$fields->push(new HeaderField(
|
||||||
|
'Header',
|
||||||
|
_t('RemoveOrphanedPagesTask.HEADER', 'Remove all orphaned pages task')
|
||||||
|
));
|
||||||
|
$fields->push(new LiteralField(
|
||||||
|
'Description',
|
||||||
|
$this->description
|
||||||
|
));
|
||||||
|
|
||||||
|
$orphans = $this->getOrphanedPages($this->orphanedSearchClass);
|
||||||
|
if($orphans) foreach($orphans as $orphan) {
|
||||||
|
$latestVersion = Versioned::get_latest_version($this->orphanedSearchClass, $orphan->ID);
|
||||||
|
$latestAuthor = DataObject::get_by_id('Member', $latestVersion->AuthorID);
|
||||||
|
$stageRecord = Versioned::get_one_by_stage(
|
||||||
|
$this->orphanedSearchClass,
|
||||||
|
'Stage',
|
||||||
|
sprintf("\"%s\".\"ID\" = %d",
|
||||||
|
ClassInfo::baseDataClass($this->orphanedSearchClass),
|
||||||
|
$orphan->ID
|
||||||
|
)
|
||||||
|
);
|
||||||
|
$liveRecord = Versioned::get_one_by_stage(
|
||||||
|
$this->orphanedSearchClass,
|
||||||
|
'Live',
|
||||||
|
sprintf("\"%s\".\"ID\" = %d",
|
||||||
|
ClassInfo::baseDataClass($this->orphanedSearchClass),
|
||||||
|
$orphan->ID
|
||||||
|
)
|
||||||
|
);
|
||||||
|
$label = sprintf(
|
||||||
|
'<a href="admin/show/%d">%s</a> <small>(#%d, Last Modified Date: %s, Last Modifier: %s, %s)</small>',
|
||||||
|
$orphan->ID,
|
||||||
|
$orphan->Title,
|
||||||
|
$orphan->ID,
|
||||||
|
DBField::create('Date', $orphan->LastEdited)->Nice(),
|
||||||
|
($latestAuthor) ? $latestAuthor->Title : 'unknown',
|
||||||
|
($liveRecord) ? 'is published' : 'not published'
|
||||||
|
);
|
||||||
|
$source[$orphan->ID] = $label;
|
||||||
|
}
|
||||||
|
|
||||||
|
if($orphans && $orphans->Count()) {
|
||||||
|
$fields->push(new CheckboxSetField('OrphanIDs', false, $source));
|
||||||
|
$fields->push(new LiteralField(
|
||||||
|
'SelectAllLiteral',
|
||||||
|
sprintf(
|
||||||
|
'<p><a href="#" onclick="javascript:jQuery(\'#Form_Form_OrphanIDs :checkbox\').attr(\'checked\', \'checked\'); return false;">%s</a> ',
|
||||||
|
_t('RemoveOrphanedPagesTask.SELECTALL', 'select all')
|
||||||
|
)
|
||||||
|
));
|
||||||
|
$fields->push(new LiteralField(
|
||||||
|
'UnselectAllLiteral',
|
||||||
|
sprintf(
|
||||||
|
'<a href="#" onclick="javascript:jQuery(\'#Form_Form_OrphanIDs :checkbox\').attr(\'checked\', \'\'); return false;">%s</a></p>',
|
||||||
|
_t('RemoveOrphanedPagesTask.UNSELECTALL', 'unselect all')
|
||||||
|
)
|
||||||
|
));
|
||||||
|
$fields->push(new OptionSetField(
|
||||||
|
'OrphanOperation',
|
||||||
|
_t('RemoveOrphanedPagesTask.CHOOSEOPERATION', 'Choose operation:'),
|
||||||
|
array(
|
||||||
|
'rebase' => _t(
|
||||||
|
'RemoveOrphanedPagesTask.OPERATION_REBASE',
|
||||||
|
sprintf(
|
||||||
|
'Rebase selected to a new holder page "%s" and unpublish. None of these pages will show up for website visitors.',
|
||||||
|
$this->rebaseHolderTitle()
|
||||||
|
)
|
||||||
|
),
|
||||||
|
'remove' => _t('RemoveOrphanedPagesTask.OPERATION_REMOVE', 'Remove selected from all stages (WARNING: Will destroy all selected pages from both stage and live)'),
|
||||||
|
),
|
||||||
|
'rebase'
|
||||||
|
));
|
||||||
|
$fields->push(new LiteralField(
|
||||||
|
'Warning',
|
||||||
|
sprintf('<p class="message">%s</p>',
|
||||||
|
_t(
|
||||||
|
'RemoveOrphanedPagesTask.DELETEWARNING',
|
||||||
|
'Warning: These operations are not reversible. Please handle with care.'
|
||||||
|
)
|
||||||
|
)
|
||||||
|
));
|
||||||
|
} else {
|
||||||
|
$fields->push(new LiteralField(
|
||||||
|
'NotFoundLabel',
|
||||||
|
sprintf(
|
||||||
|
'<p class="message">%s</p>',
|
||||||
|
_t('RemoveOrphanedPagesTask.NONEFOUND', 'No orphans found')
|
||||||
|
)
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
$form = new Form(
|
||||||
|
$this,
|
||||||
|
'Form',
|
||||||
|
$fields,
|
||||||
|
new FieldSet(
|
||||||
|
new FormAction('doSubmit', _t('RemoveOrphanedPagesTask.BUTTONRUN', 'Run'))
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
if(!$orphans || !$orphans->Count()) {
|
||||||
|
$form->makeReadonly();
|
||||||
|
}
|
||||||
|
|
||||||
|
return $form;
|
||||||
|
}
|
||||||
|
|
||||||
|
function run($request) {
|
||||||
|
// @todo Merge with BuildTask functionality
|
||||||
|
}
|
||||||
|
|
||||||
|
function doSubmit($data, $form) {
|
||||||
|
set_time_limit(60*10); // 10 minutes
|
||||||
|
|
||||||
|
if(!isset($data['OrphanIDs']) || !isset($data['OrphanOperation'])) return false;
|
||||||
|
|
||||||
|
switch($data['OrphanOperation']) {
|
||||||
|
case 'remove':
|
||||||
|
$successIDs = $this->removeOrphans($data['OrphanIDs']);
|
||||||
|
break;
|
||||||
|
case 'rebase':
|
||||||
|
$successIDs = $this->rebaseOrphans($data['OrphanIDs']);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
user_error(sprintf("Unknown operation: '%s'", $data['OrphanOperation']), E_USER_ERROR);
|
||||||
|
}
|
||||||
|
|
||||||
|
$content = '';
|
||||||
|
if($successIDs) {
|
||||||
|
$content .= "<ul>";
|
||||||
|
foreach($successIDs as $id => $label) {
|
||||||
|
$content .= sprintf('<li>%s</li>', $label);
|
||||||
|
}
|
||||||
|
$content .= "</ul>";
|
||||||
|
} else {
|
||||||
|
$content = _t('RemoveOrphanedPagesTask.NONEREMOVED', 'None removed');
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->customise(array(
|
||||||
|
'Content' => $content,
|
||||||
|
'Form' => ' '
|
||||||
|
))->renderWith('BlankPage');
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function removeOrphans($orphanIDs) {
|
||||||
|
$removedOrphans = array();
|
||||||
|
foreach($orphanIDs as $id) {
|
||||||
|
$stageRecord = Versioned::get_one_by_stage(
|
||||||
|
$this->orphanedSearchClass,
|
||||||
|
'Stage',
|
||||||
|
sprintf("\"%s\".\"ID\" = %d",
|
||||||
|
ClassInfo::baseDataClass($this->orphanedSearchClass),
|
||||||
|
$id
|
||||||
|
)
|
||||||
|
);
|
||||||
|
if($stageRecord) {
|
||||||
|
$removedOrphans[$stageRecord->ID] = sprintf('Removed %s (#%d) from Stage', $stageRecord->Title, $stageRecord->ID);
|
||||||
|
$stageRecord->delete();
|
||||||
|
$stageRecord->destroy();
|
||||||
|
unset($stageRecord);
|
||||||
|
}
|
||||||
|
$liveRecord = Versioned::get_one_by_stage(
|
||||||
|
$this->orphanedSearchClass,
|
||||||
|
'Live',
|
||||||
|
sprintf("\"%s\".\"ID\" = %d",
|
||||||
|
ClassInfo::baseDataClass($this->orphanedSearchClass),
|
||||||
|
$id
|
||||||
|
)
|
||||||
|
);
|
||||||
|
if($liveRecord) {
|
||||||
|
$removedOrphans[$liveRecord->ID] = sprintf('Removed %s (#%d) from Live', $liveRecord->Title, $liveRecord->ID);
|
||||||
|
$liveRecord->doDeleteFromLive();
|
||||||
|
$liveRecord->destroy();
|
||||||
|
unset($liveRecord);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $removedOrphans;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function rebaseHolderTitle() {
|
||||||
|
return sprintf('Rebased Orphans (%s)', date('d/m/Y g:ia', time()));
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function rebaseOrphans($orphanIDs) {
|
||||||
|
$holder = new SiteTree();
|
||||||
|
$holder->ShowInMenus = 0;
|
||||||
|
$holder->ShowInSearch = 0;
|
||||||
|
$holder->ParentID = 0;
|
||||||
|
$holder->Title = $this->rebaseHolderTitle();
|
||||||
|
$holder->write();
|
||||||
|
|
||||||
|
$removedOrphans = array();
|
||||||
|
foreach($orphanIDs as $id) {
|
||||||
|
$stageRecord = Versioned::get_one_by_stage(
|
||||||
|
$this->orphanedSearchClass,
|
||||||
|
'Stage',
|
||||||
|
sprintf("\"%s\".\"ID\" = %d",
|
||||||
|
ClassInfo::baseDataClass($this->orphanedSearchClass),
|
||||||
|
$id
|
||||||
|
)
|
||||||
|
);
|
||||||
|
if($stageRecord) {
|
||||||
|
$removedOrphans[$stageRecord->ID] = sprintf('Rebased %s (#%d)', $stageRecord->Title, $stageRecord->ID);
|
||||||
|
$stageRecord->ParentID = $holder->ID;
|
||||||
|
$stageRecord->ShowInMenus = 0;
|
||||||
|
$stageRecord->ShowInSearch = 0;
|
||||||
|
$stageRecord->write();
|
||||||
|
$stageRecord->doUnpublish();
|
||||||
|
$stageRecord->destroy();
|
||||||
|
//unset($stageRecord);
|
||||||
|
}
|
||||||
|
$liveRecord = Versioned::get_one_by_stage(
|
||||||
|
$this->orphanedSearchClass,
|
||||||
|
'Live',
|
||||||
|
sprintf("\"%s\".\"ID\" = %d",
|
||||||
|
ClassInfo::baseDataClass($this->orphanedSearchClass),
|
||||||
|
$id
|
||||||
|
)
|
||||||
|
);
|
||||||
|
if($liveRecord) {
|
||||||
|
$removedOrphans[$liveRecord->ID] = sprintf('Rebased %s (#%d)', $liveRecord->Title, $liveRecord->ID);
|
||||||
|
$liveRecord->ParentID = $holder->ID;
|
||||||
|
$liveRecord->ShowInMenus = 0;
|
||||||
|
$liveRecord->ShowInSearch = 0;
|
||||||
|
$liveRecord->write();
|
||||||
|
if(!$stageRecord) $liveRecord->doRestoreToStage();
|
||||||
|
$liveRecord->doUnpublish();
|
||||||
|
$liveRecord->destroy();
|
||||||
|
unset($liveRecord);
|
||||||
|
}
|
||||||
|
if($stageRecord) {
|
||||||
|
unset($stageRecord);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $removedOrphans;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets all orphans from "Stage" and "Live" stages.
|
||||||
|
*
|
||||||
|
* @param string $class
|
||||||
|
* @param string $filter
|
||||||
|
* @param string $sort
|
||||||
|
* @param string $join
|
||||||
|
* @param int|array $limit
|
||||||
|
* @return DataObjectSet
|
||||||
|
*/
|
||||||
|
function getOrphanedPages($class = 'SiteTree', $filter = '', $sort = null, $join = null, $limit = null) {
|
||||||
|
$filter .= ($filter) ? ' AND ' : '';
|
||||||
|
$filter .= sprintf("\"%s\".\"ParentID\" != 0 AND \"Parents\".\"ID\" IS NULL", $class);
|
||||||
|
|
||||||
|
$orphans = new DataObjectSet();
|
||||||
|
foreach(array('Stage', 'Live') as $stage) {
|
||||||
|
$joinByStage = $join;
|
||||||
|
$table = $class;
|
||||||
|
$table .= ($stage == 'Live') ? '_Live' : '';
|
||||||
|
$joinByStage .= sprintf(
|
||||||
|
"LEFT JOIN \"%s\" AS \"Parents\" ON \"%s\".\"ParentID\" = \"Parents\".\"ID\"",
|
||||||
|
$table,
|
||||||
|
$table
|
||||||
|
);
|
||||||
|
$stageOrphans = Versioned::get_by_stage(
|
||||||
|
$class,
|
||||||
|
$stage,
|
||||||
|
$filter,
|
||||||
|
$sort,
|
||||||
|
$joinByStage,
|
||||||
|
$limit
|
||||||
|
);
|
||||||
|
$orphans->merge($stageOrphans);
|
||||||
|
}
|
||||||
|
|
||||||
|
$orphans->removeDuplicates();
|
||||||
|
|
||||||
|
return $orphans;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
?>
|
51
tasks/UpgradeSiteTreePermissionSchemaTask.php
Normal file
51
tasks/UpgradeSiteTreePermissionSchemaTask.php
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* @package cms
|
||||||
|
* @subpackage tasks
|
||||||
|
*/
|
||||||
|
class UpgradeSiteTreePermissionSchemaTask extends BuildTask {
|
||||||
|
static $allowed_actions = array(
|
||||||
|
'*' => 'ADMIN'
|
||||||
|
);
|
||||||
|
|
||||||
|
protected $title = 'Upgrade SiteTree Permissions Schema';
|
||||||
|
|
||||||
|
protected $description = "Move data from legacy columns to new schema introduced in SilverStripe 2.1.<br />
|
||||||
|
SiteTree->Viewers to SiteTree->CanViewType<br />
|
||||||
|
SiteTree->Editors to SiteTree->CanEditType<br />
|
||||||
|
SiteTree->ViewersGroup to SiteTree->ViewerGroups (has_one to many_many)<br />
|
||||||
|
SiteTree->Editorsroup to SiteTree->EditorGroups (has_one to many_many)<br />
|
||||||
|
See http://open.silverstripe.com/ticket/2847
|
||||||
|
";
|
||||||
|
|
||||||
|
function run($request) {
|
||||||
|
// transfer values for changed column name
|
||||||
|
foreach(array('SiteTree','SiteTree_Live','SiteTree_versions') as $table) {
|
||||||
|
DB::query("UPDATE \"{$table}\" SET \"CanViewType\" = 'Viewers';");
|
||||||
|
DB::query("UPDATE \"{$table}\" SET \"CanEditType\" = 'Editors';");
|
||||||
|
}
|
||||||
|
//Debug::message('Moved SiteTree->Viewers to SiteTree->CanViewType');
|
||||||
|
//Debug::message('Moved SiteTree->Editors to SiteTree->CanEditType');
|
||||||
|
|
||||||
|
// convert has_many to many_many
|
||||||
|
$pageIDs = DB::query("SELECT ID FROM SiteTree")->column('ID');
|
||||||
|
foreach($pageIDs as $pageID) {
|
||||||
|
$page = DataObject::get_by_id('SiteTree', $pageID);
|
||||||
|
if($page->ViewersGroup && DataObject::get_by_id("Group", $page->ViewersGroup)) $page->ViewerGroups()->add($page->ViewersGroup);
|
||||||
|
if($page->EditorsGroup && DataObject::get_by_id("Group", $page->EditorsGroup)) $page->EditorGroups()->add($page->EditorsGroup);
|
||||||
|
|
||||||
|
$page->destroy();
|
||||||
|
unset($page);
|
||||||
|
}
|
||||||
|
//Debug::message('SiteTree->ViewersGroup to SiteTree->ViewerGroups (has_one to many_many)');
|
||||||
|
//Debug::message('SiteTree->EditorsGroup to SiteTree->EditorGroups (has_one to many_many)');
|
||||||
|
|
||||||
|
// rename legacy columns
|
||||||
|
foreach(array('SiteTree','SiteTree_Live','SiteTree_versions') as $table) {
|
||||||
|
foreach(array('Viewers','Editors','ViewersGroup','EditorsGroup') as $field) {
|
||||||
|
DB::getConn()->dontRequireField($table, $field);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
?>
|
80
tests/MigrateSiteTreeLinkingTaskTest.php
Executable file
80
tests/MigrateSiteTreeLinkingTaskTest.php
Executable file
@ -0,0 +1,80 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* @package sapphire
|
||||||
|
* @subpackage tests
|
||||||
|
*/
|
||||||
|
class MigrateSiteTreeLinkingTaskTest extends SapphireTest {
|
||||||
|
|
||||||
|
public static $fixture_file = 'cms/tests/MigrateSiteTreeLinkingTaskTest.yml';
|
||||||
|
|
||||||
|
public static $use_draft_site = true;
|
||||||
|
|
||||||
|
public function testLinkingMigration() {
|
||||||
|
ob_start();
|
||||||
|
|
||||||
|
$task = new MigrateSiteTreeLinkingTask();
|
||||||
|
$task->run(null);
|
||||||
|
|
||||||
|
$this->assertEquals (
|
||||||
|
"Rewrote 9 link(s) on 5 page(s) to use shortcodes.\n",
|
||||||
|
ob_get_contents(),
|
||||||
|
'Rewritten links are correctly reported'
|
||||||
|
);
|
||||||
|
ob_end_clean();
|
||||||
|
|
||||||
|
$homeID = $this->idFromFixture('SiteTree', 'home');
|
||||||
|
$aboutID = $this->idFromFixture('SiteTree', 'about');
|
||||||
|
$staffID = $this->idFromFixture('SiteTree', 'staff');
|
||||||
|
$actionID = $this->idFromFixture('SiteTree', 'action');
|
||||||
|
$hashID = $this->idFromFixture('SiteTree', 'hash_link');
|
||||||
|
|
||||||
|
$homeContent = sprintf (
|
||||||
|
'<a href="[sitetree_link id=%d]">About</a><a href="[sitetree_link id=%d]">Staff</a><a href="http://silverstripe.org/">External Link</a>',
|
||||||
|
$aboutID,
|
||||||
|
$staffID
|
||||||
|
);
|
||||||
|
$aboutContent = sprintf (
|
||||||
|
'<a href="[sitetree_link id=%d]">Home</a><a href="[sitetree_link id=%d]">Staff</a>',
|
||||||
|
$homeID,
|
||||||
|
$staffID
|
||||||
|
);
|
||||||
|
$staffContent = sprintf (
|
||||||
|
'<a href="[sitetree_link id=%d]">Home</a><a href="[sitetree_link id=%d]">About</a>',
|
||||||
|
$homeID,
|
||||||
|
$aboutID
|
||||||
|
);
|
||||||
|
$actionContent = sprintf (
|
||||||
|
'<a href="[sitetree_link id=%d]SearchForm">Search Form</a>', $homeID
|
||||||
|
);
|
||||||
|
$hashLinkContent = sprintf (
|
||||||
|
'<a href="[sitetree_link id=%d]#anchor">Home</a><a href="[sitetree_link id=%d]#second-anchor">About</a>',
|
||||||
|
$homeID,
|
||||||
|
$aboutID
|
||||||
|
);
|
||||||
|
|
||||||
|
$this->assertEquals (
|
||||||
|
$homeContent,
|
||||||
|
DataObject::get_by_id('SiteTree', $homeID)->Content,
|
||||||
|
'HTML URLSegment links are rewritten.'
|
||||||
|
);
|
||||||
|
$this->assertEquals (
|
||||||
|
$aboutContent,
|
||||||
|
DataObject::get_by_id('SiteTree', $aboutID)->Content
|
||||||
|
);
|
||||||
|
$this->assertEquals (
|
||||||
|
$staffContent,
|
||||||
|
DataObject::get_by_id('SiteTree', $staffID)->Content
|
||||||
|
);
|
||||||
|
$this->assertEquals (
|
||||||
|
$actionContent,
|
||||||
|
DataObject::get_by_id('SiteTree', $actionID)->Content,
|
||||||
|
'Links to actions on pages are rewritten correctly.'
|
||||||
|
);
|
||||||
|
$this->assertEquals (
|
||||||
|
$hashLinkContent,
|
||||||
|
DataObject::get_by_id('SiteTree', $hashID)->Content,
|
||||||
|
'Hash/anchor links are correctly handled.'
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
67
tests/MigrateSiteTreeLinkingTaskTest.yml
Executable file
67
tests/MigrateSiteTreeLinkingTaskTest.yml
Executable file
@ -0,0 +1,67 @@
|
|||||||
|
SiteTree:
|
||||||
|
home:
|
||||||
|
Title: Home Page
|
||||||
|
URLSegment: home
|
||||||
|
Content: '<a href="about/">About</a><a href="staff">Staff</a><a href="http://silverstripe.org/">External Link</a>'
|
||||||
|
about:
|
||||||
|
Title: About Us
|
||||||
|
URLSegment: about
|
||||||
|
Content: <a href="home">Home</a><a href="staff/">Staff</a>
|
||||||
|
staff:
|
||||||
|
Title: Staff
|
||||||
|
URLSegment: staff
|
||||||
|
Content: <a href="home/">Home</a><a href="about">About</a>
|
||||||
|
Parent: =>SiteTree.about
|
||||||
|
action:
|
||||||
|
Title: Action Link
|
||||||
|
URLSegment: action
|
||||||
|
Content: <a href="home/SearchForm">Search Form</a>
|
||||||
|
hash_link:
|
||||||
|
Title: Hash Link
|
||||||
|
URLSegment: hash-link
|
||||||
|
Content: '<a href="home/#anchor">Home</a><a href="about/#second-anchor">About</a>'
|
||||||
|
admin_link:
|
||||||
|
Title: Admin Link
|
||||||
|
URLSegment: admin-link
|
||||||
|
Content: <a href="admin">Admin</a>
|
||||||
|
no_links:
|
||||||
|
Title: No Links
|
||||||
|
URLSegment: No Links
|
||||||
|
|
||||||
|
SiteTree_LinkTracking:
|
||||||
|
home_about:
|
||||||
|
SiteTreeID: =>SiteTree.home
|
||||||
|
ChildID: =>SiteTree.about
|
||||||
|
FieldName: Content
|
||||||
|
home_staff:
|
||||||
|
SiteTreeID: =>SiteTree.home
|
||||||
|
ChildID: =>SiteTree.staff
|
||||||
|
FieldName: Content
|
||||||
|
about_home:
|
||||||
|
SiteTreeID: =>SiteTree.about
|
||||||
|
ChildID: =>SiteTree.home
|
||||||
|
FieldName: Content
|
||||||
|
about_staff:
|
||||||
|
SiteTreeID: =>SiteTree.about
|
||||||
|
ChildID: =>SiteTree.staff
|
||||||
|
FieldName: Content
|
||||||
|
staff_home:
|
||||||
|
SiteTreeID: =>SiteTree.staff
|
||||||
|
ChildID: =>SiteTree.home
|
||||||
|
FieldName: Content
|
||||||
|
staff_about:
|
||||||
|
SiteTreeID: =>SiteTree.staff
|
||||||
|
ChildID: =>SiteTree.about
|
||||||
|
FieldName: Content
|
||||||
|
action_home:
|
||||||
|
SiteTreeID: =>SiteTree.action
|
||||||
|
ChildID: =>SiteTree.home
|
||||||
|
FieldName: Content
|
||||||
|
hash_link_home:
|
||||||
|
SiteTreeID: =>SiteTree.hash_link
|
||||||
|
ChildID: =>SiteTree.home
|
||||||
|
FieldName: Content
|
||||||
|
hash_link_about:
|
||||||
|
SiteTreeID: =>SiteTree.hash_link
|
||||||
|
ChildID: =>SiteTree.about
|
||||||
|
FieldName: Content
|
105
tests/RemoveOrphanedPagesTaskTest.php
Normal file
105
tests/RemoveOrphanedPagesTaskTest.php
Normal file
@ -0,0 +1,105 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* <h2>Fixture tree</h2>
|
||||||
|
* <code>
|
||||||
|
* parent1_published
|
||||||
|
* child1_1_published
|
||||||
|
* grandchild1_1_1
|
||||||
|
* grandchild1_1_2_published
|
||||||
|
* grandchild1_1_3_orphaned
|
||||||
|
* grandchild1_1_4_orphaned_published
|
||||||
|
* child1_2_published
|
||||||
|
* child1_3_orphaned
|
||||||
|
* child1_4_orphaned_published
|
||||||
|
* parent2
|
||||||
|
* child2_1_published_orphaned // is orphaned because parent is not published
|
||||||
|
* </code>
|
||||||
|
*
|
||||||
|
* <h2>Cleaned up tree</h2>
|
||||||
|
* <code>
|
||||||
|
* parent1_published
|
||||||
|
* child1_1_published
|
||||||
|
* grandchild1_1_1
|
||||||
|
* grandchild1_1_2_published
|
||||||
|
* child2_1_published_orphaned
|
||||||
|
* parent2
|
||||||
|
* </code>
|
||||||
|
*
|
||||||
|
* @author Ingo Schommer (<firstname>@silverstripe.com), SilverStripe Ltd.
|
||||||
|
*
|
||||||
|
* @package sapphire
|
||||||
|
* @subpackage tests
|
||||||
|
*/
|
||||||
|
class RemoveOrphanedPagesTaskTest extends FunctionalTest {
|
||||||
|
|
||||||
|
static $fixture_file = 'sapphire/tests/tasks/RemoveOrphanedPagesTaskTest.yml';
|
||||||
|
|
||||||
|
static $use_draft_site = false;
|
||||||
|
|
||||||
|
function setUp() {
|
||||||
|
parent::setUp();
|
||||||
|
|
||||||
|
$parent1_published = $this->objFromFixture('Page', 'parent1_published');
|
||||||
|
$parent1_published->publish('Stage', 'Live');
|
||||||
|
|
||||||
|
$child1_1_published = $this->objFromFixture('Page', 'child1_1_published');
|
||||||
|
$child1_1_published->publish('Stage', 'Live');
|
||||||
|
|
||||||
|
$child1_2_published = $this->objFromFixture('Page', 'child1_2_published');
|
||||||
|
$child1_2_published->publish('Stage', 'Live');
|
||||||
|
|
||||||
|
$child1_3_orphaned = $this->objFromFixture('Page', 'child1_3_orphaned');
|
||||||
|
$child1_3_orphaned->ParentID = 9999;
|
||||||
|
$child1_3_orphaned->write();
|
||||||
|
|
||||||
|
$child1_4_orphaned_published = $this->objFromFixture('Page', 'child1_4_orphaned_published');
|
||||||
|
$child1_4_orphaned_published->ParentID = 9999;
|
||||||
|
$child1_4_orphaned_published->write();
|
||||||
|
$child1_4_orphaned_published->publish('Stage', 'Live');
|
||||||
|
|
||||||
|
$grandchild1_1_2_published = $this->objFromFixture('Page', 'grandchild1_1_2_published');
|
||||||
|
$grandchild1_1_2_published->publish('Stage', 'Live');
|
||||||
|
|
||||||
|
$grandchild1_1_3_orphaned = $this->objFromFixture('Page', 'grandchild1_1_3_orphaned');
|
||||||
|
$grandchild1_1_3_orphaned->ParentID = 9999;
|
||||||
|
$grandchild1_1_3_orphaned->write();
|
||||||
|
|
||||||
|
$grandchild1_1_4_orphaned_published = $this->objFromFixture('Page',
|
||||||
|
'grandchild1_1_4_orphaned_published'
|
||||||
|
);
|
||||||
|
$grandchild1_1_4_orphaned_published->ParentID = 9999;
|
||||||
|
$grandchild1_1_4_orphaned_published->write();
|
||||||
|
$grandchild1_1_4_orphaned_published->publish('Stage', 'Live');
|
||||||
|
|
||||||
|
$child2_1_published_orphaned = $this->objFromFixture('Page', 'child2_1_published_orphaned');
|
||||||
|
$child2_1_published_orphaned->publish('Stage', 'Live');
|
||||||
|
}
|
||||||
|
|
||||||
|
function testGetOrphansByStage() {
|
||||||
|
// all orphans
|
||||||
|
$child1_3_orphaned = $this->objFromFixture('Page', 'child1_3_orphaned');
|
||||||
|
$child1_4_orphaned_published = $this->objFromFixture('Page', 'child1_4_orphaned_published');
|
||||||
|
$grandchild1_1_3_orphaned = $this->objFromFixture('Page', 'grandchild1_1_3_orphaned');
|
||||||
|
$grandchild1_1_4_orphaned_published = $this->objFromFixture('Page',
|
||||||
|
'grandchild1_1_4_orphaned_published'
|
||||||
|
);
|
||||||
|
$child2_1_published_orphaned = $this->objFromFixture('Page', 'child2_1_published_orphaned');
|
||||||
|
|
||||||
|
$task = singleton('RemoveOrphanedPagesTask');
|
||||||
|
$orphans = $task->getOrphanedPages();
|
||||||
|
$orphanIDs = $orphans->column('ID');
|
||||||
|
sort($orphanIDs);
|
||||||
|
$compareIDs = array(
|
||||||
|
$child1_3_orphaned->ID,
|
||||||
|
$child1_4_orphaned_published->ID,
|
||||||
|
$grandchild1_1_3_orphaned->ID,
|
||||||
|
$grandchild1_1_4_orphaned_published->ID,
|
||||||
|
$child2_1_published_orphaned->ID
|
||||||
|
);
|
||||||
|
sort($compareIDs);
|
||||||
|
|
||||||
|
$this->assertEquals($orphanIDs, $compareIDs);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
?>
|
32
tests/RemoveOrphanedPagesTaskTest.yml
Normal file
32
tests/RemoveOrphanedPagesTaskTest.yml
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
Page:
|
||||||
|
parent1_published:
|
||||||
|
Title: Parent1
|
||||||
|
child1_1_published:
|
||||||
|
Title: Child1.1
|
||||||
|
Parent: =>Page.parent1_published
|
||||||
|
child1_2_published:
|
||||||
|
Title: Child1.2
|
||||||
|
Parent: =>Page.parent1_published
|
||||||
|
child1_3_orphaned:
|
||||||
|
Title: Child1.3
|
||||||
|
Parent: =>Page.parent1_published
|
||||||
|
child1_4_orphaned_published:
|
||||||
|
Title: Child1.4
|
||||||
|
Parent: =>Page.parent1_published
|
||||||
|
grandchild1_1_1:
|
||||||
|
Title: Grandchild1.1.1
|
||||||
|
Parent: =>Page.child1_1_published
|
||||||
|
grandchild1_1_2_published:
|
||||||
|
Title: Grandchild1.1.2
|
||||||
|
Parent: =>Page.child1_1_published
|
||||||
|
grandchild1_1_3_orphaned:
|
||||||
|
Title: Grandchild1.1.3
|
||||||
|
Parent: =>Page.child1_1_published
|
||||||
|
grandchild1_1_4_orphaned_published:
|
||||||
|
Title: Grandchild1.1.4
|
||||||
|
Parent: =>Page.child1_1_published
|
||||||
|
parent2:
|
||||||
|
Title: Parent2
|
||||||
|
child2_1_published_orphaned:
|
||||||
|
Title: Child2.1
|
||||||
|
Parent: =>Page.parent2
|
Loading…
Reference in New Issue
Block a user