API Cleaned up versioned status checks

This commit is contained in:
Damian Mooyman 2016-10-05 14:16:09 +13:00
parent d7ded0fb4a
commit 380d6523c5
No known key found for this signature in database
GPG Key ID: 78B823A10DE27D1A
4 changed files with 133 additions and 57 deletions

View File

@ -475,9 +475,9 @@ class File extends DataObject implements ShortcodeHandler, AssetContainer, Thumb
$previewLink = Convert::raw2att($this->PreviewLink());
$image = "<img src=\"{$previewLink}\" class=\"editor__thumbnail\" />";
$statusTitle = $this->getStatusTitle();
$statusFlag = ($statusTitle) ? "<span class=\"editor__status-flag\">{$statusTitle}</span>" : '';
$statusFlag = ($statusTitle) ? "<span class=\"editor__status-flag\">{$statusTitle}</span>" : '';
$content = Tab::create('Main',
HeaderField::create('TitleHeader', $this->Title, 1)
@ -515,18 +515,22 @@ class File extends DataObject implements ShortcodeHandler, AssetContainer, Thumb
return $fields;
}
protected function getStatusTitle() {
/**
* Get title for current file status
*
* @return string
*/
public function getStatusTitle() {
$statusTitle = '';
if ($this->getIsAddedToStage()) {
if ($this->isOnDraftOnly()) {
$statusTitle = _t('File.DRAFT', 'Draft');
} elseif ($this->getIsModifiedOnStage()) {
} elseif ($this->isModifiedOnDraft()) {
$statusTitle = _t('File.MODIFIED', 'Modified');
}
return $statusTitle;
}
/**
* Returns a category based on the file extension.
* This can be useful when grouping files by type,

View File

@ -1774,9 +1774,8 @@ class Versioned extends DataExtension implements TemplateGlobalProvider {
public function stagesDiffer($stage1, $stage2) {
$table1 = $this->baseTable($stage1);
$table2 = $this->baseTable($stage2);
$owner = $this->owner;
if(!is_numeric($owner->ID)) {
$id = $this->owner->ID ?: $this->owner->OldID;
if (!$id) {
return true;
}
@ -1788,7 +1787,7 @@ class Versioned extends DataExtension implements TemplateGlobalProvider {
"SELECT CASE WHEN \"$table1\".\"Version\"=\"$table2\".\"Version\" THEN 1 ELSE 0 END
FROM \"$table1\" INNER JOIN \"$table2\" ON \"$table1\".\"ID\" = \"$table2\".\"ID\"
AND \"$table1\".\"ID\" = ?",
array($owner->ID)
array($id)
)->value();
return !$stagesAreEqual;
@ -2292,8 +2291,8 @@ class Versioned extends DataExtension implements TemplateGlobalProvider {
* @return bool
*/
public function isPublished() {
$owner = $this->owner;
if(!$owner->isInDB()) {
$id = $this->owner->ID ?: $this->owner->OldID;
if(!$id) {
return false;
}
@ -2305,78 +2304,68 @@ class Versioned extends DataExtension implements TemplateGlobalProvider {
$table = $this->baseTable(static::LIVE);
$result = DB::prepared_query(
"SELECT COUNT(*) FROM \"{$table}\" WHERE \"{$table}\".\"ID\" = ?",
array($owner->ID)
array($id)
);
return (bool)$result->value();
}
/**
* Check if page doesn't exist on any stage, but used to be
*
* @return bool
*/
public function isArchived() {
$id = $this->owner->ID ?: $this->owner->OldID;
return $id && !$this->isOnDraft() && !$this->isPublished();
}
/**
* Check if this record exists on the draft stage
*
* @return bool
*/
public function isOnDraft() {
$owner = $this->owner;
if(!$owner->isInDB()) {
$id = $this->owner->ID ?: $this->owner->OldID;
if(!$id) {
return false;
}
$table = $this->baseTable();
$result = DB::prepared_query(
"SELECT COUNT(*) FROM \"{$table}\" WHERE \"{$table}\".\"ID\" = ?",
array($owner->ID)
array($id)
);
return (bool)$result->value();
}
/**
* Compares current draft with live version, and returns true if no draft version of this page exists but the page
* is still published (eg, after triggering "Delete from draft site" in the CMS).
*
* @return bool
*/
public function getIsDeletedFromStage() {
if(!$this->owner->ID) return true;
$stageVersion = Versioned::get_versionnumber_by_stage($this->owner->class, Versioned::DRAFT, $this->owner->ID);
// Return true for both completely deleted pages and for pages just deleted from stage
return !($stageVersion);
public function isOnLiveOnly() {
return $this->isPublished() && !$this->isOnDraft();
}
/**
* Compares current draft with live version, and returns true if these versions differ, meaning there have been
* unpublished changes to the draft site.
*
* @return bool
*/
public function getIsModifiedOnStage() {
// New unsaved pages could be never be published
if(!$this->owner->ID) return false;
$stageVersion = Versioned::get_versionnumber_by_stage($this->owner->class, 'Stage', $this->owner->ID);
$liveVersion = Versioned::get_versionnumber_by_stage($this->owner->class, 'Live', $this->owner->ID);
$isModified = ($stageVersion && $stageVersion != $liveVersion);
$this->owner->extend('updateIsModifiedOnStage', $isModified);
return $isModified;
}
/**
* Compares current draft with live version, and returns true if no live version exists, meaning the page was never
* published.
*
* @return bool
*/
public function getIsAddedToStage() {
// New unsaved pages could be never be published
if(!$this->owner->ID) return false;
$stageVersion = Versioned::get_versionnumber_by_stage($this->owner->class, 'Stage', $this->owner->ID);
$liveVersion = Versioned::get_versionnumber_by_stage($this->owner->class, 'Live', $this->owner->ID);
return ($stageVersion && !$liveVersion);
public function isOnDraftOnly() {
return $this->isOnDraft() && !$this->isPublished();
}
/**
* Compares current draft with live version, and returns true if these versions differ, meaning there have been
* unpublished changes to the draft site.
*
* @return bool
*/
public function isModifiedOnDraft() {
return $this->isOnDraft() && $this->stagesDiffer(Versioned::DRAFT, Versioned::LIVE);
}
/**

View File

@ -887,10 +887,18 @@ A very small number of methods were chosen for deprecation, and will be removed
* Any extension declared via `versionableExtensions` config on Versioned dataobject must now
`VersionableExtension` interface at a minimum. `Translatable` has been removed from default
`versionableExtensions`
* A lot of standard versioned API has been refactored from `SiteTree` into `Versioned` extension. Now
all versioned DataObjects have `canPublish()`, `canArchive()`, `canUnpublish()`, `doPublish()`, `doArchive()`
`doUnpublish()`, `isPublished()` and `isonDraft()` out of the box. However, `do*()` methods will no longer
automatically check `can*()` permissions, and must be done by usercode before invocation.
* A lot of standard versioned API has been refactored from `SiteTree` into `Versioned` extension.
* All versioned DataObjects have `canPublish()`, `canArchive()`, `canUnpublish()` permission checks
* All versioned Dataobjects have `doPublish()`, `doArchive()`, `doPublish()`, and `doUnpublish()` actions.
However, `do*()` methods will no longer automatically check `can*()` permissions, and must be done by
usercode before invocation.
* `SiteTree::getIsAddedToStage()` moved to `Versioned` and renamed to `isOnDraftOnly()`
* `SiteTre::getIsModifiedOnStage()` moved to `Versioned` and renamed to `isModifiedOnDraft()`
* `SiteTree::isPublished()` moved to `Versioned`.
* `SiteTree::getExistsOnLive()` removed in favour of `isPublished()`
* `isOnDraft()` added to `Versioned`.
* `isArchived()` added to `Versioned`.
* `isOnLiveOnly()` added to `Versioned`.
* `ChangeSet` and `ChangeSetItem` have been added for batch publishing of versioned dataobjects.
* `DataObject.table_name` config can now be used to customise the database table for any record.
* `DataObjectSchema` class added to assist with mapping between classes and tables.
@ -903,6 +911,8 @@ A very small number of methods were chosen for deprecation, and will be removed
* Removed `UpgradeSiteTreePermissionSchemaTask`
* Removed `EncryptAllPasswordsTask`
* Removed `DBString::LimitWordCountXML()` method. Use `LimitWordCount` for XML safe version.
* Removed `SiteTree::getExistsOnLive()`. Use `isPublished()` instead.
* Removed `SiteTree::getIsDeletedFromStage()`. Use `isOnDraft()` instead (inverse case).
### <a name="overview-filesystem"></a>Filesystem API

View File

@ -1,6 +1,8 @@
<?php
use SilverStripe\ORM\DB;
use SilverStripe\ORM\HasManyList;
use SilverStripe\ORM\ManyManyList;
use SilverStripe\ORM\Versioning\Versioned;
use SilverStripe\ORM\DataObject;
use SilverStripe\ORM\FieldType\DBDatetime;
@ -1087,6 +1089,77 @@ class VersionedTest extends SapphireTest {
$this->assertEquals(2, $version->Version);
$this->assertEquals($record->Title, $version->Title);
}
public function testStageStates() {
// newly created page
$createdPage = new VersionedTest_DataObject();
$createdPage->write();
$this->assertTrue($createdPage->isOnDraft());
$this->assertFalse($createdPage->isPublished());
$this->assertTrue($createdPage->isOnDraftOnly());
$this->assertTrue($createdPage->isModifiedOnDraft());
// published page
$publishedPage = new VersionedTest_DataObject();
$publishedPage->write();
$publishedPage->copyVersionToStage('Stage','Live');
$this->assertTrue($publishedPage->isOnDraft());
$this->assertTrue($publishedPage->isPublished());
$this->assertFalse($publishedPage->isOnDraftOnly());
$this->assertFalse($publishedPage->isOnLiveOnly());
$this->assertFalse($publishedPage->isModifiedOnDraft());
// published page, deleted from stage
$deletedFromDraftPage = new VersionedTest_DataObject();
$deletedFromDraftPage->write();
$deletedFromDraftPage->copyVersionToStage('Stage','Live');
$deletedFromDraftPage->deleteFromStage('Stage');
$this->assertFalse($deletedFromDraftPage->isArchived());
$this->assertFalse($deletedFromDraftPage->isOnDraft());
$this->assertTrue($deletedFromDraftPage->isPublished());
$this->assertFalse($deletedFromDraftPage->isOnDraftOnly());
$this->assertTrue($deletedFromDraftPage->isOnLiveOnly());
$this->assertFalse($deletedFromDraftPage->isModifiedOnDraft());
// published page, deleted from live
$deletedFromLivePage = new VersionedTest_DataObject();
$deletedFromLivePage->write();
$deletedFromLivePage->copyVersionToStage('Stage','Live');
$deletedFromLivePage->deleteFromStage('Live');
$this->assertFalse($deletedFromLivePage->isArchived());
$this->assertTrue($deletedFromLivePage->isOnDraft());
$this->assertFalse($deletedFromLivePage->isPublished());
$this->assertTrue($deletedFromLivePage->isOnDraftOnly());
$this->assertFalse($deletedFromLivePage->isOnLiveOnly());
$this->assertTrue($deletedFromLivePage->isModifiedOnDraft());
// published page, deleted from both stages
$deletedFromAllStagesPage = new VersionedTest_DataObject();
$deletedFromAllStagesPage->write();
$deletedFromAllStagesPage->copyVersionToStage('Stage','Live');
$deletedFromAllStagesPage->doArchive();
$this->assertTrue($deletedFromAllStagesPage->isArchived());
$this->assertFalse($deletedFromAllStagesPage->isOnDraft());
$this->assertFalse($deletedFromAllStagesPage->isPublished());
$this->assertFalse($deletedFromAllStagesPage->isOnDraftOnly());
$this->assertFalse($deletedFromAllStagesPage->isOnLiveOnly());
$this->assertFalse($deletedFromAllStagesPage->isModifiedOnDraft());
// published page, modified
$modifiedOnDraftPage = new VersionedTest_DataObject();
$modifiedOnDraftPage->write();
$modifiedOnDraftPage->copyVersionToStage('Stage','Live');
$modifiedOnDraftPage->Content = 'modified';
$modifiedOnDraftPage->write();
$this->assertFalse($modifiedOnDraftPage->isArchived());
$this->assertTrue($modifiedOnDraftPage->isOnDraft());
$this->assertTrue($modifiedOnDraftPage->isPublished());
$this->assertFalse($modifiedOnDraftPage->isOnDraftOnly());
$this->assertFalse($modifiedOnDraftPage->isOnLiveOnly());
$this->assertTrue($modifiedOnDraftPage->isModifiedOnDraft());
}
}