Skip to content

Commit

Permalink
API Move logic from silverstripe/cms into central place (#11460)
Browse files Browse the repository at this point in the history
This logic is used by CMSMain but needs to be callable on any
hierarchical model.

In some cases this logic is generic enough it could be on any model or
any DataObject
  • Loading branch information
GuySartorelli authored Nov 26, 2024
1 parent 574b4e8 commit 26d5b11
Show file tree
Hide file tree
Showing 27 changed files with 1,201 additions and 76 deletions.
59 changes: 57 additions & 2 deletions src/Forms/GridField/GridFieldDataColumns.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,12 @@
use InvalidArgumentException;
use LogicException;
use SilverStripe\Model\ModelData;
use SilverStripe\Dev\Deprecation;

/**
* @see GridField
*/
class GridFieldDataColumns extends AbstractGridFieldComponent implements GridField_ColumnProvider
{

/**
* @var array
*/
Expand All @@ -31,6 +29,15 @@ class GridFieldDataColumns extends AbstractGridFieldComponent implements GridFie
*/
protected $displayFields = [];

private bool $displayStatusFlags = true;

private array $columnsForStatusFlag = [
'Title',
'Name',
];

private ?string $statusFlagColumn = null;

/**
* Modify the list of columns displayed in the table.
* See {@link GridFieldDataColumns->getDisplayFields()} and {@link GridFieldDataColumns}.
Expand All @@ -44,6 +51,10 @@ public function augmentColumns($gridField, &$columns)

foreach ($baseColumns as $col) {
$columns[] = $col;
// Find the column to add status flags to
if ($this->statusFlagColumn === null && in_array($col, $this->getColumnsForStatusFlag())) {
$this->statusFlagColumn = $col;
}
}

$columns = array_unique($columns ?? []);
Expand All @@ -60,6 +71,45 @@ public function getColumnsHandled($gridField)
return array_keys($this->getDisplayFields($gridField) ?? []);
}

/**
* Set whether status flags are displayed in this gridfield
*/
public function setDisplayStatusFlags(bool $display): static
{
$this->displayStatusFlags = $display;
return $this;
}

/**
* Get whether status flags are displayed in this gridfield
*/
public function getDisplayStatusFlags(): bool
{
return $this->displayStatusFlags;
}

/**
* Set which columns can be used to display the status flags.
* The first column from this list found in the gridfield will be used.
*/
public function setColumnsForStatusFlag(array $columns): static
{
if (empty($columns)) {
throw new InvalidArgumentException('Columns array must not be empty');
}
$this->columnsForStatusFlag = $columns;
return $this;
}

/**
* Get which columns can be used to display the status flags.
* The first column from this list found in the gridfield will be used.
*/
public function getColumnsForStatusFlag(): array
{
return $this->columnsForStatusFlag;
}

/**
* Override the default behaviour of showing the models summaryFields with
* these fields instead
Expand Down Expand Up @@ -183,6 +233,11 @@ public function getColumnContent($gridField, $record, $columnName)
// Do any final escaping
$value = $this->escapeValue($gridField, $value);

// Add on status flags
if ($this->getDisplayStatusFlags() && $columnName === $this->statusFlagColumn) {
$value .= $record->getStatusFlagMarkup('ss-gridfield-badge');
}

return $value;
}

Expand Down
12 changes: 10 additions & 2 deletions src/Forms/GridField/GridFieldDetailForm_ItemRequest.php
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
use SilverStripe\View\HTML;
use SilverStripe\View\SSViewer;
use SilverStripe\Model\ModelData;
use SilverStripe\ORM\FieldType\DBField;

class GridFieldDetailForm_ItemRequest extends RequestHandler
{
Expand Down Expand Up @@ -930,11 +931,13 @@ public function Breadcrumbs($unlinked = false)
$items = $this->popupController->Breadcrumbs($unlinked);

if (!$items) {
/** @var ArrayList<ArrayData> $items */
$items = ArrayList::create();
}

if ($this->record && $this->record->ID) {
$title = ($this->record->Title) ? $this->record->Title : "#{$this->record->ID}";
$record = $this->getRecord();
if ($record && $record->ID) {
$title = ($record->Title) ? $record->Title : "#{$record->ID}";
$items->push(ArrayData::create([
'Title' => $title,
'Link' => $this->Link()
Expand All @@ -952,6 +955,11 @@ public function Breadcrumbs($unlinked = false)
}
}

$statusFlags = $record->getStatusFlagMarkup('badge--breadcrumbs');
if ($statusFlags) {
$items->last()->setField('Extra', DBField::create_field('HTMLFragment', $statusFlags));
}

$this->extend('updateBreadcrumbs', $items);
return $items;
}
Expand Down
61 changes: 61 additions & 0 deletions src/Model/ModelData.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
use SilverStripe\ORM\FieldType\DBHTMLText;
use SilverStripe\Model\ArrayData;
use SilverStripe\View\CastingService;
use SilverStripe\View\HTML;
use SilverStripe\View\SSViewer;
use UnexpectedValueException;

Expand Down Expand Up @@ -47,6 +48,7 @@ class ModelData
private static array $casting = [
'CSSClasses' => 'Varchar',
'forTemplate' => 'HTMLText',
'StatusFlagMarkup' => 'HTMLFragment',
];

/**
Expand Down Expand Up @@ -74,6 +76,8 @@ class ModelData

private array $objCache = [];

private $_cache_statusFlags = null;

public function __construct()
{
// no-op
Expand Down Expand Up @@ -487,6 +491,52 @@ public function hasValue(string $field, array $arguments = [], bool $cache = tru

// UTILITY METHODS -------------------------------------------------------------------------------------------------

/**
* Flags provides the user with additional data about the current page status.
*
* Mostly this is used for versioning, but can be used for other purposes (e.g. localisation).
* Each page can have more than one status flag.
*
* Returns an associative array of a unique key to a (localized) title for the flag.
* The unique key can be reused as a CSS class.
*
* Example (simple):
* "deletedonlive" => "Deleted"
*
* Example (with optional title attribute):
* "deletedonlive" => ['text' => "Deleted", 'title' => 'This page has been deleted']
*/
public function getStatusFlags(bool $cached = true): array
{
if (!$this->_cache_statusFlags || !$cached) {
$flags = [];
$this->extend('updateStatusFlags', $flags);
$this->_cache_statusFlags = $flags;
}
return $this->_cache_statusFlags;
}

/**
* Get the HTML markup for rendering status flags for this model.
*/
public function getStatusFlagMarkup(string $additionalCssClass = ''): string
{
$flagContent = '';
foreach ($this->getStatusFlags() as $class => $data) {
$flagAttributes = [
'class' => rtrim("badge status-{$class} $additionalCssClass"),
];
if (is_string($data)) {
$data = ['text' => $data];
}
if (isset($data['title'])) {
$flagAttributes['title'] = $data['title'];
}
$flagContent .= HTML::createTag('span', $flagAttributes, Convert::raw2xml($data['text']));
}
return $flagContent;
}

/**
* Find appropriate templates for SSViewer to use to render this object
*/
Expand Down Expand Up @@ -545,6 +595,17 @@ public function Debug(): ModelData|string
return ModelDataDebugger::create($this);
}

/**
* Clears record-specific cached data.
*/
public function flushCache(): static
{
$this->objCacheClear();
$this->_cache_statusFlags = null;
$this->extend('onFlushCache');
return $this;
}

/**
* Generate the cache name for a field
*/
Expand Down
50 changes: 13 additions & 37 deletions src/ORM/DataObject.php
Original file line number Diff line number Diff line change
Expand Up @@ -116,17 +116,13 @@ class DataObject extends ModelData implements DataObjectInterface, i18nEntityPro
{
/**
* Human-readable singular name.
* @var string
* @config
*/
private static $singular_name = null;
private static ?string $singular_name = null;

/**
* Human-readable plural name
* @var string
* @config
*/
private static $plural_name = null;
private static ?string $plural_name = null;

/**
* Description of the class.
Expand All @@ -150,7 +146,6 @@ class DataObject extends ModelData implements DataObjectInterface, i18nEntityPro
* @var string
*/
private static $default_classname = null;

/**
* Whether this DataObject class must only use the primary database and not a read-only replica
* Note that this will be only be enforced when using DataQuery::execute() or
Expand Down Expand Up @@ -957,40 +952,23 @@ public function i18n_plural_name()

/**
* Get description for this class
* @return null|string
*/
public function classDescription()
public function classDescription(): ?string
{
return static::config()->get('class_description', Config::UNINHERITED);
}

/**
* Get localised description for this class
* @return null|string
*/
public function i18n_classDescription()
public function i18n_classDescription(): ?string
{
$notDefined = 'NOT_DEFINED';
$baseDescription = $this->classDescription() ?? $notDefined;

// Check the new i18n key first
$description = _t(static::class . '.CLASS_DESCRIPTION', $baseDescription);
if ($description !== $baseDescription) {
return $description;
}

// Fall back on the deprecated localisation key
$legacyI18n = _t(static::class . '.DESCRIPTION', $baseDescription);
if ($legacyI18n !== $baseDescription) {
return $legacyI18n;
}

// If there was no description available in config nor in i18n, return null
if ($baseDescription === $notDefined) {
$description = _t(static::class.'.CLASS_DESCRIPTION', $this->classDescription() ?? $notDefined);
if ($description === $notDefined) {
return null;
}
// Return raw description
return $baseDescription;
return $description;
}

/**
Expand Down Expand Up @@ -3562,14 +3540,14 @@ public static function get_one($callerClass = null, $filter = "", $cache = true,
}

/**
* Flush the cached results for all relations (has_one, has_many, many_many)
* Also clears any cached aggregate data.
* @inheritDoc
*
* Also flush the cached results for all relations (has_one, has_many, many_many)
*
* @param boolean $persistent When true will also clear persistent data stored in the Cache system.
* @param bool $persistent When true will also clear persistent data stored in the Cache system.
* When false will just clear session-local cached data
* @return static $this
*/
public function flushCache($persistent = true)
public function flushCache(bool $persistent = true): static
{
if (static::class == DataObject::class) {
DataObject::$_cache_get_one = [];
Expand All @@ -3583,11 +3561,9 @@ public function flushCache($persistent = true)
}
}

$this->extend('onFlushCache');

$this->components = [];
$this->eagerLoadedData = [];
return $this;
return parent::flushCache();
}

/**
Expand Down
11 changes: 0 additions & 11 deletions src/ORM/FieldType/DBEnum.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
use SilverStripe\Core\Config\Config;
use SilverStripe\Core\Validation\FieldValidation\OptionFieldValidator;
use SilverStripe\Core\Resettable;
use SilverStripe\Dev\Deprecation;
use SilverStripe\Forms\DropdownField;
use SilverStripe\Forms\FormField;
use SilverStripe\Forms\SelectField;
Expand Down Expand Up @@ -43,16 +42,6 @@ class DBEnum extends DBString implements Resettable
*/
protected static array $enum_cache = [];

/**
* Clear all cached enum values.
* @deprecated 5.4.0 Use reset() instead.
*/
public static function flushCache(): void
{
Deprecation::notice('5.4.0', 'Use reset() instead.');
static::reset();
}

public static function reset(): void
{
DBEnum::$enum_cache = [];
Expand Down
Loading

0 comments on commit 26d5b11

Please sign in to comment.