diff --git a/_config/versionedgridfield.yml b/_config/versionedgridfield.yml index 23c08919..9e446ee3 100644 --- a/_config/versionedgridfield.yml +++ b/_config/versionedgridfield.yml @@ -7,14 +7,9 @@ SilverStripe\Forms\GridField\GridFieldDetailForm: # Add status row to gridfields by default SilverStripe\Forms\GridField\GridFieldConfig_RecordEditor: extensions: - - SilverStripe\Versioned\VersionedGridFieldStateExtension - SilverStripe\Versioned\VersionedGridFieldArchiveExtension -SilverStripe\Forms\GridField\GridFieldConfig_Base: - extensions: - - SilverStripe\Versioned\VersionedGridFieldStateExtension SilverStripe\Forms\GridField\GridFieldConfig_RelationEditor: extensions: - - SilverStripe\Versioned\VersionedGridFieldStateExtension - SilverStripe\Versioned\VersionedGridFieldArchiveExtension # Enable gridfield extensions for dataobjects by default SilverStripe\ORM\DataObject: diff --git a/src/Versioned.php b/src/Versioned.php index 87858e5a..f4e56f9e 100644 --- a/src/Versioned.php +++ b/src/Versioned.php @@ -2981,4 +2981,42 @@ public function Publisher() $member = DataObject::get_by_id(Member::class, $this->owner->PublisherID); return $member; } + + protected function updateStatusFlags(array &$flags): void + { + if ($this->isOnLiveOnly()) { + $flags['removedfromdraft'] = [ + 'text' => _t(__CLASS__ . '.FLAG_ONLIVEONLY_SHORT', 'On live only'), + 'title' => _t( + __CLASS__ . '.FLAG_ONLIVEONLYSHORT_HELP', + 'Item is published, but has been deleted from draft' + ), + ]; + return; + } + + if ($this->isArchived()) { + $flags['archived'] = [ + 'text' => _t(__CLASS__ . '.FLAG_ARCHIVED_SHORT', 'Archived'), + 'title' => _t(__CLASS__ . '.FLAG_ARCHIVED_HELP', 'Item is removed from draft and live'), + ]; + return; + } + + if ($this->isOnDraftOnly()) { + $flags['addedtodraft'] = [ + 'text' => _t(__CLASS__ . '.FLAG_ADDEDTODRAFT_SHORT', 'Draft'), + 'title' => _t(__CLASS__ . '.FLAG_ADDEDTODRAFT_HELP', 'Item has not been published yet') + ]; + return; + } + + if ($this->isModifiedOnDraft()) { + $flags['modified'] = [ + 'text' => _t(__CLASS__ . '.FLAG_MODIFIEDONDRAFT_SHORT', 'Modified'), + 'title' => _t(__CLASS__ . '.FLAG_MODIFIEDONDRAFT_HELP', 'Item has unpublished changes'), + ]; + return; + } + } } diff --git a/src/VersionedGridFieldItemRequest.php b/src/VersionedGridFieldItemRequest.php index fdcefabf..e05bd4e8 100644 --- a/src/VersionedGridFieldItemRequest.php +++ b/src/VersionedGridFieldItemRequest.php @@ -12,11 +12,8 @@ use SilverStripe\Forms\LiteralField; use SilverStripe\Forms\Tab; use SilverStripe\Forms\TabSet; -use SilverStripe\Model\List\ArrayList; use SilverStripe\ORM\DataObject; -use SilverStripe\ORM\FieldType\DBField; use SilverStripe\Core\Validation\ValidationResult; -use SilverStripe\Model\ArrayData; use SilverStripe\View\SSViewer; /** @@ -26,29 +23,6 @@ */ class VersionedGridFieldItemRequest extends GridFieldDetailForm_ItemRequest { - public function Breadcrumbs($unlinked = false) - { - $items = parent::Breadcrumbs($unlinked); - $status = $this->getRecordStatus(); - $badge = null; - if ($status) { - // Generate badge - $badge = DBField::create_field('HTMLFragment', sprintf( - '%s', - $status['class'], - $status['title'] - )); - } - $this->extend('updateBadge', $badge); - - if ($badge) { - $lastItem = $items->last(); - $lastItem->setField('Extra', $badge); - } - - return $items; - } - /** * @return FieldList */ @@ -244,38 +218,6 @@ protected function setFormMessage($form, $message) } } - /** - * Return list of class / title to add on the end of record status in breadcrumbs - * - * @return array|null - */ - protected function getRecordStatus() - { - /** @var DataObject|Versioned $record */ - $record = $this->record; - - // No status if un-versioned - if (!$this->record->hasExtension(Versioned::class)) { - return null; - } - - if ($record->isOnDraftOnly()) { - return [ - 'class' => 'addedtodraft', - 'title' => _t(__CLASS__ . '.DRAFT', 'Draft') - ]; - } - - if ($record->isModifiedOnDraft()) { - return [ - 'class' => 'modified', - 'title' => _t(__CLASS__ . '.MODIFIED', 'Modified') - ]; - } - - return null; - } - /** * Getting buttons that are for versioned objects * diff --git a/src/VersionedGridFieldState/VersionedGridFieldState.php b/src/VersionedGridFieldState/VersionedGridFieldState.php deleted file mode 100644 index 65b5dda6..00000000 --- a/src/VersionedGridFieldState/VersionedGridFieldState.php +++ /dev/null @@ -1,239 +0,0 @@ -setVersionedLabelFields($versionedLabelFields); - } - - /** - * Column to decorate with version state - * - * @return string - */ - public function getColumn() - { - return $this->column; - } - - /** - * @param string $column - * @return VersionedGridFieldState - */ - public function setColumn($column) - { - $this->column = $column; - return $this; - } - - /** - * Search list for default column - * - * @return array - */ - public function getVersionedLabelFields() - { - return $this->versionedLabelFields; - } - - /** - * @param array $versionedLabelFields - * @return VersionedGridFieldState - */ - public function setVersionedLabelFields($versionedLabelFields) - { - $this->versionedLabelFields = $versionedLabelFields; - return $this; - } - - /** - * Modify the list of columns displayed in the table. - * - * @see {@link GridFieldDataColumns->getDisplayFields()} - * @see {@link GridFieldDataColumns}. - * - * @param GridField $gridField - * @param array $columns List reference of all column names. - */ - public function augmentColumns($gridField, &$columns) - { - $model = $gridField->getModelClass(); - $isModelVersioned = $model::has_extension(Versioned::class); - - // Skip if not versioned, or column already set - if (!$isModelVersioned || $this->getColumn()) { - return; - } - - $matchedVersionedFields = array_intersect( - $columns ?? [], - $this->versionedLabelFields - ); - - if (count($matchedVersionedFields ?? []) > 0) { - // Get first matched column - $this->setColumn(reset($matchedVersionedFields)); - } elseif ($columns) { - // Use first column if none of preferred matches - $this->setColumn(reset($columns)); - } - } - - /** - * Names of all columns which are affected by this component. - * - * @param GridField $gridField - * @return array - */ - public function getColumnsHandled($gridField) - { - return $this->getColumn() ? [$this->getColumn()] : []; - } - - /** - * HTML for the column, content of the element. - * - * @param GridField $gridField - * @param DataObject $record Record displayed in this row - * @param string $columnName - * @return string HTML for the column. Return NULL to skip. - */ - public function getColumnContent($gridField, $record, $columnName) - { - $flagContent = ''; - $flags = $this->getStatusFlags($record); - foreach ($flags as $class => $data) { - $flagAttributes = [ - 'class' => "ss-gridfield-badge badge status-{$class}", - ]; - if (isset($data['title'])) { - $flagAttributes['title'] = $data['title']; - } - $flagContent .= ' ' . HTML::createTag('span', $flagAttributes, Convert::raw2xml($data['text'])); - } - return $flagContent; - } - - /** - * Attributes for the element containing the content returned by {@link getColumnContent()}. - * - * @param GridField $gridField - * @param DataObject $record displayed in this row - * @param string $columnName - * @return array - */ - public function getColumnAttributes($gridField, $record, $columnName) - { - return []; - } - - /** - * Additional metadata about the column which can be used by other components, - * e.g. to set a title for a search column header. - * - * @param GridField $gridField - * @param string $columnName - * @return array - Map of arbitrary metadata identifiers to their values. - */ - public function getColumnMetadata($gridField, $columnName) - { - return []; - } - - - /** - * A flag provides the user with additional data about the current item - * status, for example a "removed from draft" status. Each item can have - * more than one status flag. Returns a map of a unique key to a - * (localized) title for the flag. The unique key can be reused as a CSS - * class. - * - * Example (simple): - * - * ```php - * "deletedonlive" => "Deleted" - * ``` - * - * Example (with optional title attribute): - * - * ```php - * "deletedonlive" => array( - * 'text' => "Deleted", - * 'title' => 'This page has been deleted' - * ) - * ``` - * - * @param Versioned|DataObject $record - the record to check status for - * @return array - */ - protected function getStatusFlags($record) - { - if (!$record->hasExtension(Versioned::class)) { - return []; - } - - if ($record->isOnLiveOnly()) { - return [ - 'removedfromdraft' => [ - 'text' => _t(__CLASS__ . '.ONLIVEONLYSHORT', 'On live only'), - 'title' => _t( - __CLASS__ . '.ONLIVEONLYSHORTHELP', - 'Item is published, but has been deleted from draft' - ), - ] - ]; - } - - if ($record->isArchived()) { - return [ - 'archived' => [ - 'text' => _t(__CLASS__ . '.ARCHIVEDPAGESHORT', 'Archived'), - 'title' => _t(__CLASS__ . '.ARCHIVEDPAGEHELP', 'Item is removed from draft and live'), - ] - ]; - } - - if ($record->isOnDraftOnly()) { - return [ - 'addedtodraft' => [ - 'text' => _t(__CLASS__ . '.ADDEDTODRAFTSHORT', 'Draft'), - 'title' => _t(__CLASS__ . '.ADDEDTODRAFTHELP', "Item has not been published yet") - ] - ]; - } - - if ($record->isModifiedOnDraft()) { - return [ - 'modified' => [ - 'text' => _t(__CLASS__ . '.MODIFIEDONDRAFTSHORT', 'Modified'), - 'title' => _t(__CLASS__ . '.MODIFIEDONDRAFTHELP', 'Item has unpublished changes'), - ] - ]; - } - - return []; - } -} diff --git a/src/VersionedGridFieldStateExtension.php b/src/VersionedGridFieldStateExtension.php deleted file mode 100644 index c5130cbc..00000000 --- a/src/VersionedGridFieldStateExtension.php +++ /dev/null @@ -1,23 +0,0 @@ - - */ -class VersionedGridFieldStateExtension extends Extension -{ - protected function updateConfig() - { - $owner = $this->getOwner(); - if (!$owner->getComponentByType(VersionedGridFieldState::class)) { - $owner->addComponent(new VersionedGridFieldState()); - } - } -} diff --git a/tests/php/VersionedTest.php b/tests/php/VersionedTest.php index 3539fd78..9f6e47c2 100644 --- a/tests/php/VersionedTest.php +++ b/tests/php/VersionedTest.php @@ -6,6 +6,8 @@ use InvalidArgumentException; use ReflectionMethod; use DMS\PHPUnitExtensions\ArraySubset\ArraySubsetAsserts; +use LogicException; +use PHPUnit\Framework\Attributes\DataProvider; use SilverStripe\Control\Controller; use SilverStripe\Control\Director; use SilverStripe\Control\HTTPRequest; @@ -1700,4 +1702,94 @@ public function testLiveObjectDeletedOnUnpublish() $obj->doUnpublish(); $this->assertEquals('First name', VersionedTest\TestObject::$nameValueOfObjectJustDeleted); } + + public static function provideUpdateStatusFlags(): array + { + return [ + 'new record no status' => [ + 'status' => 'new', + 'expected' => [], + ], + 'saved to draft' => [ + 'status' => 'draft', + 'expected' => [ + 'addedtodraft' => [ + 'text' => 'Draft', + 'title' => 'Item has not been published yet', + ], + ], + ], + 'saved and published' => [ + 'status' => 'published', + 'expected' => [], + ], + 'published but deleted on draft' => [ + 'status' => 'published only', + 'expected' => [ + 'removedfromdraft' => [ + 'text' => 'On live only', + 'title' => 'Item is published, but has been deleted from draft', + ], + ], + ], + 'published but modified on draft' => [ + 'status' => 'modified', + 'expected' => [ + 'modified' => [ + 'text' => 'Modified', + 'title' => 'Item has unpublished changes', + ], + ], + ], + 'archived' => [ + 'status' => 'archived', + 'expected' => [ + 'archived' => [ + 'text' => 'Archived', + 'title' => 'Item is removed from draft and live', + ], + ], + ], + ]; + } + + #[DataProvider('provideUpdateStatusFlags')] + public function testUpdateStatusFlags(string $status, array $expected): void + { + /** @var VersionedTest\TestObject&Versioned */ + $record = new VersionedTest\TestObject(); + + switch ($status) { + case 'new': + // no-op + break; + case 'draft': + $record->write(); + break; + case 'published': + $record->write(); + $record->publishSingle(); + break; + case 'published only': + $record->write(); + $record->publishSingle(); + $record->deleteFromStage(Versioned::DRAFT); + break; + case 'modified': + $record->write(); + $record->publishSingle(); + $record->Name = 'modified record'; + $record->write(); + break; + case 'archived': + $record->write(); + $record->publishSingle(); + $record->doArchive(); + break; + default: + throw new LogicException("Status $status not accounted for"); + } + + $this->assertSame($expected, $record->getStatusFlags()); + } }