diff --git a/src/Forms/GridField/GridField.php b/src/Forms/GridField/GridField.php
index 2590aa758..9cbd42adb 100644
--- a/src/Forms/GridField/GridField.php
+++ b/src/Forms/GridField/GridField.php
@@ -319,6 +319,10 @@ class GridField extends FormField
$this->config->addComponent(GridState_Component::create());
}
+ if (!$this->config->getComponentByType(GridFieldVersionTag::class)) {
+ $this->config->addComponent(GridFieldVersionTag::create());
+ }
+
return $this;
}
diff --git a/src/Forms/GridField/GridFieldDetailForm_ItemRequest.php b/src/Forms/GridField/GridFieldDetailForm_ItemRequest.php
index 252b270bd..91d79433a 100644
--- a/src/Forms/GridField/GridFieldDetailForm_ItemRequest.php
+++ b/src/Forms/GridField/GridFieldDetailForm_ItemRequest.php
@@ -10,6 +10,7 @@ use SilverStripe\Control\HTTPResponse;
use SilverStripe\Control\RequestHandler;
use SilverStripe\Core\Convert;
use SilverStripe\Core\ClassInfo;
+use SilverStripe\Core\Injector\Injector;
use SilverStripe\Forms\CompositeField;
use SilverStripe\Forms\FieldList;
use SilverStripe\Forms\Form;
@@ -19,6 +20,7 @@ use SilverStripe\Forms\LiteralField;
use SilverStripe\ORM\ArrayList;
use SilverStripe\ORM\DataObject;
use SilverStripe\ORM\DataObjectInterface;
+use SilverStripe\ORM\FieldType\DBField;
use SilverStripe\ORM\FieldType\DBHTMLText;
use SilverStripe\ORM\HasManyList;
use SilverStripe\ORM\ManyManyList;
@@ -27,6 +29,7 @@ use SilverStripe\ORM\RelationList;
use SilverStripe\ORM\SS_List;
use SilverStripe\ORM\ValidationException;
use SilverStripe\ORM\ValidationResult;
+use SilverStripe\Versioned\RecursiveStagesInterface;
use SilverStripe\View\ArrayData;
use SilverStripe\View\HTML;
use SilverStripe\View\SSViewer;
@@ -417,7 +420,7 @@ class GridFieldDetailForm_ItemRequest extends RequestHandler
throw new LogicException(get_class($this->record) . ' must implement ' . DataObjectInterface::class);
}
- $noChangesClasses = 'btn-outline-primary font-icon-tick';
+ $noChangesClasses = $this->stagesDifferRecursive() ? 'btn-primary font-icon-save' : 'btn-outline-primary font-icon-tick';
$majorActions->push(FormAction::create('doSave', _t('SilverStripe\\Forms\\GridField\\GridFieldDetailForm.Save', 'Save'))
->addExtraClass($noChangesClasses)
->setAttribute('data-btn-alternate-add', 'btn-primary font-icon-save')
@@ -936,6 +939,25 @@ class GridFieldDetailForm_ItemRequest extends RequestHandler
}
}
+ $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) {
+ /** @var ArrayData $lastItem */
+ $lastItem = $items->last();
+ $lastItem->setField('Extra', $badge);
+ }
+
$this->extend('updateBreadcrumbs', $items);
return $items;
}
@@ -947,4 +969,25 @@ class GridFieldDetailForm_ItemRequest extends RequestHandler
}
return ClassInfo::shortName($this->record);
}
+
+ private function getRecordStatus(): ?array
+ {
+ if ($this->stagesDifferRecursive()) {
+ return [
+ 'class' => 'modified',
+ 'title' => _t(__CLASS__ . '.MODIFIED', 'Modified')
+ ];
+ }
+
+ return null;
+ }
+
+
+ private function stagesDifferRecursive(): bool
+ {
+ /** @var RecursiveStagesInterface $service */
+ $service = Injector::inst()->get(RecursiveStagesInterface::class);
+
+ return $service->stagesDifferRecursive($this->record);
+ }
}
diff --git a/src/Forms/GridField/GridFieldVersionTag.php b/src/Forms/GridField/GridFieldVersionTag.php
new file mode 100644
index 000000000..3381f5ea8
--- /dev/null
+++ b/src/Forms/GridField/GridFieldVersionTag.php
@@ -0,0 +1,160 @@
+setVersionedLabelFields($versionedLabelFields);
+ }
+
+ public function getColumn(): ?string
+ {
+ return $this->column;
+ }
+
+ public function setColumn(string $column): static
+ {
+ $this->column = $column;
+ return $this;
+ }
+
+ public function getVersionedLabelFields(): array
+ {
+ return $this->versionedLabelFields;
+ }
+
+ public function setVersionedLabelFields(array $versionedLabelFields): static
+ {
+ $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): void
+ {
+ // Skip if not versioned, or column already set
+ if ($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): array
+ {
+ 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.
+ */
+ public function getColumnContent($gridField, $record, $columnName): string
+ {
+ $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 column
+ */
+ public function getColumnAttributes($gridField, $record, $columnName): array
+ {
+ return [];
+ }
+
+ /**
+ * Metadata for the column
+ */
+ public function getColumnMetadata($gridField, $columnName): array
+ {
+ return [];
+ }
+
+ /**
+ * Get status flags for a given record
+ */
+ private function getStatusFlags(DataObject $record): array
+ {
+ if ($record->hasExtension(Versioned::class)) {
+ return [];
+ }
+
+ if ($this->stagesDifferRecursive($record)) {
+ return [
+ 'modified' => [
+ 'text' => _t(__CLASS__ . '.MODIFIEDONDRAFTSHORT', 'Modified'),
+ 'title' => _t(__CLASS__ . '.MODIFIEDONDRAFTHELP', 'Item has unpublished changes'),
+ ]
+ ];
+ }
+
+ return [];
+ }
+
+ /**
+ * Check if stages differ for a given record and all its relations
+ */
+ private function stagesDifferRecursive(DataObject $record): bool
+ {
+ /** @var RecursiveStagesInterface $service */
+ $service = Injector::inst()->get(RecursiveStagesInterface::class);
+
+ return $service->stagesDifferRecursive($record);
+ }
+}
diff --git a/tests/php/Forms/GridField/GridFieldDetailForm_ItemRequestTest.php b/tests/php/Forms/GridField/GridFieldDetailForm_ItemRequestTest.php
index 0a13a0749..f45a96aeb 100644
--- a/tests/php/Forms/GridField/GridFieldDetailForm_ItemRequestTest.php
+++ b/tests/php/Forms/GridField/GridFieldDetailForm_ItemRequestTest.php
@@ -4,18 +4,37 @@ namespace SilverStripe\Forms\Tests\GridField;
use LogicException;
use SilverStripe\Control\Controller;
+use SilverStripe\Admin\LeftAndMain;
use SilverStripe\Dev\SapphireTest;
+use SilverStripe\Forms\FieldList;
+use SilverStripe\Forms\Form;
use SilverStripe\Forms\GridField\GridField;
use SilverStripe\Forms\GridField\GridFieldConfig_Base;
use SilverStripe\Forms\GridField\GridFieldDetailForm;
use SilverStripe\Forms\GridField\GridFieldDetailForm_ItemRequest;
+use SilverStripe\Forms\Tests\GridField\GridFieldTest\Cheerleader;
+use SilverStripe\Forms\Tests\GridField\GridFieldTest\Team;
use SilverStripe\ORM\ArrayList;
use SilverStripe\View\ArrayData;
+use SilverStripe\Versioned\Versioned;
class GridFieldDetailForm_ItemRequestTest extends SapphireTest
{
protected $usesDatabase = false;
+ protected static $fixture_file = 'GridFieldDetailForm_ItemRequestTest.yml';
+
+ protected static $extra_dataobjects = [
+ Cheerleader::class,
+ Team::class,
+ ];
+
+ protected static $required_extensions = [
+ Cheerleader::class => [
+ Versioned::class,
+ ],
+ ];
+
public function testItemEditFormThrowsException()
{
$gridField = new GridField('dummy', 'dummy', new ArrayList(), new GridFieldConfig_Base());
@@ -31,4 +50,24 @@ class GridFieldDetailForm_ItemRequestTest extends SapphireTest
$itemRequest->ItemEditForm();
}
+
+ public function testBreadcrumbs()
+ {
+ $team = Team::get();
+ $cheerleader = Cheerleader::get()->first();
+ $form = new Form(null, 'Form', new FieldList(), new FieldList());
+ $gridField = new GridField('TestGridField', 'TestGridFields', $team);
+ $gridField->setForm($form);
+
+ $itemRequest = new GridFieldDetailForm_ItemRequest(
+ $gridField,
+ new GridFieldDetailForm(),
+ $team->first(),
+ new LeftandMain(),
+ '',
+ );
+
+ $item = $itemRequest->Breadcrumbs()->last()->toMap();
+ $this->assertTrue(array_key_exists('Extra', $item));
+ }
}
diff --git a/tests/php/Forms/GridField/GridFieldDetailForm_ItemRequestTest.yml b/tests/php/Forms/GridField/GridFieldDetailForm_ItemRequestTest.yml
new file mode 100644
index 000000000..8899cf2af
--- /dev/null
+++ b/tests/php/Forms/GridField/GridFieldDetailForm_ItemRequestTest.yml
@@ -0,0 +1,8 @@
+SilverStripe\Forms\Tests\GridField\GridFieldTest\Team:
+ team1:
+ Name: Team 1
+ City: Cologne
+SilverStripe\Forms\Tests\GridField\GridFieldTest\Cheerleader:
+ cheerleader1_team1:
+ Name: Heather
+ Team: =>SilverStripe\Forms\Tests\GridField\GridFieldTest\Team.team1
diff --git a/tests/php/Forms/GridField/GridFieldTest.php b/tests/php/Forms/GridField/GridFieldTest.php
index 642460aa5..521c48fb9 100644
--- a/tests/php/Forms/GridField/GridFieldTest.php
+++ b/tests/php/Forms/GridField/GridFieldTest.php
@@ -24,6 +24,7 @@ use SilverStripe\Forms\GridField\GridFieldToolbarHeader;
use SilverStripe\Forms\GridField\GridState;
use SilverStripe\Forms\GridField\GridState_Component;
use SilverStripe\Forms\GridField\GridState_Data;
+use SilverStripe\Forms\GridField\GridFieldVersionTag;
use SilverStripe\Forms\RequiredFields;
use SilverStripe\Forms\Tests\GridField\GridFieldTest\Cheerleader;
use SilverStripe\Forms\Tests\GridField\GridFieldTest\Component;
@@ -96,6 +97,7 @@ class GridFieldTest extends SapphireTest
new GridFieldPageCount('toolbar-header-right'),
$pagination = new GridFieldPaginator(),
new GridState_Component(),
+ new GridFieldVersionTag(),
]);
$sort->setThrowExceptionOnBadDataType(false);
$filter->setThrowExceptionOnBadDataType(false);
@@ -122,6 +124,7 @@ class GridFieldTest extends SapphireTest
0 => new GridFieldSortableHeader,
1 => new GridFieldDataColumns,
2 => new GridState_Component,
+ 3 => new GridFieldVersionTag,
]
);
diff --git a/tests/php/Forms/GridField/GridFieldTest/Team.php b/tests/php/Forms/GridField/GridFieldTest/Team.php
index 42e296653..b4e24d998 100644
--- a/tests/php/Forms/GridField/GridFieldTest/Team.php
+++ b/tests/php/Forms/GridField/GridFieldTest/Team.php
@@ -18,6 +18,10 @@ class Team extends DataObject implements TestOnly
'Players' => Player::class
];
+ private static $owns = [
+ 'Cheerleaders'
+ ];
+
private static $has_many = [
'Cheerleaders' => Cheerleader::class
];
diff --git a/tests/php/Forms/GridField/GridFieldVersionTagTest.php b/tests/php/Forms/GridField/GridFieldVersionTagTest.php
new file mode 100644
index 000000000..a2d23b3a3
--- /dev/null
+++ b/tests/php/Forms/GridField/GridFieldVersionTagTest.php
@@ -0,0 +1,77 @@
+ [
+ Versioned::class,
+ ],
+ ];
+
+ public function testGetColumnContent()
+ {
+ $team = Team::get();
+ $cheerleader = Cheerleader::get()->first();
+ $gridField = new GridField('TestGridField', 'TestGridFields', $team);
+
+ $columns = $gridField->getConfig()->getComponentByType(GridFieldVersionTag::class);
+ $nameColumn = $columns->getColumnContent($gridField, $team->first(), 'Name');
+ $this->assertEquals(
+ $nameColumn,
+ ' Modified'
+ );
+
+ $cheerleader->publishRecursive();
+ $nameColumn = $columns->getColumnContent($gridField, $team->first(), 'Name');
+
+ $this->assertEquals($nameColumn, '');
+ }
+
+ public function testAugmentColumns()
+ {
+ $team = Team::get();
+ $cheerleader = Cheerleader::get()->first();
+ $gridField = new GridField('TestGridField', 'TestGridFields', $team);
+
+ $columns = $gridField->getConfig()->getComponentByType(GridFieldVersionTag::class);
+
+ $columns->setVersionedLabelFields(['Title']);
+ $column = $columns->getVersionedLabelFields();
+
+ $this->assertEquals($column, ['Title']);
+
+ $augmentColumns = ['Name', 'Title', 'ID'];
+
+ $columns->augmentColumns($gridField, $augmentColumns);
+ $nameColumn = $columns->getColumn();
+
+ $this->assertEquals($nameColumn, 'Title');
+
+ $columns->setVersionedLabelFields(['Non-Title']);
+ $column = $columns->getVersionedLabelFields();
+
+ $this->assertEquals($column, ['Non-Title']);
+
+ $columns->augmentColumns($gridField, $augmentColumns);
+ $nameColumn = $columns->getColumn();
+
+ $this->assertNotEquals($nameColumn, 'Non-Title');
+ $this->assertEquals($nameColumn, 'Title');
+ }
+}
diff --git a/tests/php/Forms/GridField/GridFieldVersionTagTest.yml b/tests/php/Forms/GridField/GridFieldVersionTagTest.yml
new file mode 100644
index 000000000..8899cf2af
--- /dev/null
+++ b/tests/php/Forms/GridField/GridFieldVersionTagTest.yml
@@ -0,0 +1,8 @@
+SilverStripe\Forms\Tests\GridField\GridFieldTest\Team:
+ team1:
+ Name: Team 1
+ City: Cologne
+SilverStripe\Forms\Tests\GridField\GridFieldTest\Cheerleader:
+ cheerleader1_team1:
+ Name: Heather
+ Team: =>SilverStripe\Forms\Tests\GridField\GridFieldTest\Team.team1
|