diff --git a/Assets/File.php b/Assets/File.php index 074b287ad..0d2f006a0 100644 --- a/Assets/File.php +++ b/Assets/File.php @@ -475,10 +475,14 @@ class File extends DataObject implements ShortcodeHandler, AssetContainer, Thumb $previewLink = Convert::raw2att($this->PreviewLink()); $image = ""; + + $statusTitle = $this->getStatusTitle(); + $statusFlag = ($statusTitle) ? "{$statusTitle}" : ''; $content = Tab::create('Main', HeaderField::create('TitleHeader', $this->Title, 1) ->addExtraClass('editor__heading'), + LiteralField::create('StatusFlag', $statusFlag), LiteralField::create("IconFull", $image) ->addExtraClass('editor__file-preview'), TabSet::create('Editor', @@ -511,7 +515,18 @@ class File extends DataObject implements ShortcodeHandler, AssetContainer, Thumb return $fields; } - + + protected function getStatusTitle() { + $statusTitle = ''; + if ($this->getIsAddedToStage()) { + $statusTitle = _t('File.DRAFT', 'Draft'); + } elseif ($this->getIsModifiedOnStage()) { + $statusTitle = _t('File.MODIFIED', 'Modified'); + } + + return $statusTitle; + } + /** * Returns a category based on the file extension. * This can be useful when grouping files by type, diff --git a/Assets/Image.php b/Assets/Image.php index 44fee744d..82f1354d4 100644 --- a/Assets/Image.php +++ b/Assets/Image.php @@ -51,6 +51,9 @@ class Image extends File implements ShortcodeHandler { $image = ""; $link = $this->Link(); + + $statusTitle = $this->getStatusTitle(); + $statusFlag = "{$statusTitle}"; $content = Tab::create('Main', HeaderField::create('TitleHeader', $this->Title, 1) @@ -92,10 +95,15 @@ class Image extends File implements ShortcodeHandler { 'TitleHeader', LiteralField::create( "DisplaySize", - sprintf('
%spx, %s
', - $dimensions, $this->getSize()) + sprintf('
%spx, %s %s
', + $dimensions, $this->getSize(), $statusFlag) ) ); + } else { + $content->insertAfter( + 'TitleHeader', + LiteralField::create('StatusFlag', $statusFlag) + ); } $fields = FieldList::create(TabSet::create('Root', $content)); diff --git a/ORM/Versioning/Versioned.php b/ORM/Versioning/Versioned.php index 07f746007..94de2679b 100644 --- a/ORM/Versioning/Versioned.php +++ b/ORM/Versioning/Versioned.php @@ -2328,8 +2328,56 @@ class Versioned extends DataExtension implements TemplateGlobalProvider { ); 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); + } + + /** + * 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); + } /** * Return the equivalent of a DataList::create() call, querying the latest diff --git a/client/lang/en.js b/client/lang/en.js index e09c9b2b1..8c5a42845 100644 --- a/client/lang/en.js +++ b/client/lang/en.js @@ -7,6 +7,9 @@ if (typeof(ss) === 'undefined' || typeof(ss.i18n) === 'undefined') { } else { ss.i18n.addDictionary('en', { "FormField.NONE": "None", + "File.DRAFT": "Draft", + "File.MODIFIED": "Modified", + "File.PUBLISHED": "Published", "FILEIFRAMEFIELD.CONFIRMDELETE": "Are you sure you want to delete this file?", "FILEIFRAMEFIELD.DELETEFILE": "Delete File", "FILEIFRAMEFIELD.DELETEIMAGE": "Delete Image", @@ -47,4 +50,4 @@ if (typeof(ss) === 'undefined' || typeof(ss.i18n) === 'undefined') { "UploadField.WRITEFAILED": "Failed to write file to disk", "VALIDATOR.FIELDREQUIRED": "Please fill out \"%s\", it is required." }); -} +} \ No newline at end of file diff --git a/client/lang/src/en.js b/client/lang/src/en.js index 4a5374967..3754d41ce 100644 --- a/client/lang/src/en.js +++ b/client/lang/src/en.js @@ -1,5 +1,8 @@ { - "FormField.NONE": "None", + "FormField.NONE": "None", + "File.DRAFT": "Draft", + "File.MODIFIED": "Modified", + "File.PUBLISHED": "Published", "FILEIFRAMEFIELD.CONFIRMDELETE": "Are you sure you want to delete this file?", "FILEIFRAMEFIELD.DELETEFILE": "Delete File", "FILEIFRAMEFIELD.DELETEIMAGE": "Delete Image", diff --git a/lang/en.yml b/lang/en.yml index 97026e337..2e33baf17 100644 --- a/lang/en.yml +++ b/lang/en.yml @@ -202,6 +202,7 @@ en: CssType: 'CSS file' DmgType: 'Apple disk image' DocType: 'Word document' + DRAFT: 'Draft' Filename: Filename GifType: 'GIF image - good for diagrams' GzType: 'GZIP compressed file' @@ -212,6 +213,7 @@ en: IcoType: 'Icon image' JpgType: 'JPEG image - good for photos' JsType: 'Javascript file' + MODIFIED: 'Modified' Mp3Type: 'MP3 audio file' MpgType: 'MPEG video file' NOFILESIZE: 'Filesize is zero bytes.' @@ -220,6 +222,7 @@ en: PLURALNAME: Files PdfType: 'Adobe Acrobat PDF file' PngType: 'PNG image - good general-purpose format' + PUBLISHED: 'Published' SINGULARNAME: File TOOLARGE: 'Filesize is too large, maximum {size} allowed' TOOLARGESHORT: 'File size exceeds {size}'