From 0113c90c765a16cbd4131c40f938b7b1fa32a395 Mon Sep 17 00:00:00 2001 From: Guy Sartorelli Date: Wed, 20 Nov 2024 15:45:51 +1300 Subject: [PATCH] ENH Update status flags generally, not just for SiteTree --- src/Extension/FluentExtension.php | 109 ++++++++++++++++++ src/Extension/FluentGridFieldExtension.php | 15 --- src/Extension/FluentLeftAndMainExtension.php | 22 ---- src/Extension/FluentSiteTreeExtension.php | 104 ----------------- src/Extension/FluentVersionedExtension.php | 70 +++++++++++ .../Extension/FluentBadgeExtensionTest.php | 97 +++++++++------- .../Extension/FluentBadgeExtensionTest.yml | 16 ++- 7 files changed, 244 insertions(+), 189 deletions(-) diff --git a/src/Extension/FluentExtension.php b/src/Extension/FluentExtension.php index eeffef9c..bde51b28 100644 --- a/src/Extension/FluentExtension.php +++ b/src/Extension/FluentExtension.php @@ -27,6 +27,7 @@ use SilverStripe\Security\Permission; use SilverStripe\Versioned\Versioned; use SilverStripe\View\HTML; +use TractorCow\Fluent\Extension\Traits\FluentBadgeTrait; use TractorCow\Fluent\Extension\Traits\FluentObjectTrait; use TractorCow\Fluent\Forms\CopyLocaleAction; use TractorCow\Fluent\Forms\GroupActionMenu; @@ -1286,6 +1287,114 @@ protected function findRecordInLocale($locale, $table, $id) return $query->firstRow()->execute()->value() !== null; } + /** + * Remove fluent status flags from site tree display + */ + protected function updateStatusFlagsForTreeTitle(array &$flags): void + { + foreach (array_keys($flags) as $key) { + if ($key === 'fluent' || str_starts_with($key, 'fluent ')) { + unset($flags[$key]); + } + } + } + + /** + * Update status flags based on whether the current record is exists in the current locale. + */ + protected function updateStatusFlags(array &$flags): void + { + // If there is no current FluentState, then we shouldn't update. + if (!FluentState::singleton()->getLocale()) { + return; + } + $this->addLocaleFlags($flags); + $this->updateNoSourceFlag($flags); + } + + /** + * Add a flag based on the record's status in the current locale. + */ + private function addLocaleFlags(array &$flags): void + { + $locale = Locale::getCurrentLocale(); + $record = $this->getOwner(); + $info = RecordLocale::create($record, $locale); + + // Build new badge + if ($info->IsDraft()) { + // If the object has been localised in the current locale, show a "localised" state + $flags['fluent fluent-badge fluent-badge--default'] = [ + 'title' => _t( + FluentBadgeTrait::class . '.BadgeLocalised', + 'Localised in {locale}', + [ + 'locale' => $locale->getTitle() + ] + ), + 'text' => $locale->getLocale(), + ]; + } elseif ($info->getSourceLocale()) { + // If object is inheriting content from another locale show the source + $flags['fluent fluent-badge fluent-badge--localised'] = [ + 'title' => _t( + FluentBadgeTrait::class . '.BadgeLocalised', + 'Localised in {locale}', + [ + 'locale' => $info->getSourceLocale()->getTitle() + ] + ), + 'text' => $info->getSourceLocale()->getLocale(), + ]; + } else { + // Otherwise the object is missing a content source and needs to be remedied + // by either localising or seting up a locale fallback + $flags['fluent fluent-badge fluent-badge--invisible'] = [ + 'title' => _t( + FluentBadgeTrait::class . '.BaggeInvisible', + '{type} has no available content in {locale}, localise the {type} or provide a locale fallback', + [ + 'type' => $record->i18n_singular_name(), + 'locale' => $locale->getTitle(), + ] + ), + 'text' => $locale->getLocale(), + ]; + } + } + + /** + * Add a flag which indicates that a record has content in other locale but the content is not being inherited + */ + protected function updateNoSourceFlag(array &$flags): void + { + if (array_key_exists('archived', $flags)) { + return; + } + + $locale = FluentState::singleton()->getLocale(); + + if (!$locale) { + return; + } + + $owner = $this->getOwner(); + $info = $owner->LocaleInformation($locale); + + if ($info->getSourceLocale()) { + return; + } + + if (!$owner->getLocaleInstances()) { + return; + } + + $flags['removedfromdraft'] = [ + 'text' => 'No source', + 'title' => 'This page exists in a different locale but the content is not inherited', + ]; + } + /** * @param $summaryColumns * @see FluentObjectTrait::updateFluentCMSFields() diff --git a/src/Extension/FluentGridFieldExtension.php b/src/Extension/FluentGridFieldExtension.php index 27a8e9e2..a4859401 100644 --- a/src/Extension/FluentGridFieldExtension.php +++ b/src/Extension/FluentGridFieldExtension.php @@ -8,12 +8,10 @@ use SilverStripe\Forms\FieldList; use SilverStripe\Forms\Form; use SilverStripe\Forms\GridField\GridFieldDetailForm_ItemRequest; -use SilverStripe\ORM\FieldType\DBField; use SilverStripe\ORM\FieldType\DBHTMLText; use SilverStripe\Core\Validation\ValidationResult; use SilverStripe\Versioned\VersionedGridFieldItemRequest; use TractorCow\Fluent\Extension\Traits\FluentAdminTrait; -use TractorCow\Fluent\Extension\Traits\FluentBadgeTrait; /** * Supports GridFieldDetailForm_ItemRequest with extra actions @@ -23,19 +21,6 @@ class FluentGridFieldExtension extends Extension { use FluentAdminTrait; - use FluentBadgeTrait; - - /** - * Push a badge to indicate the language that owns the current item - * - * @param DBField|null $badgeField - * @see VersionedGridFieldItemRequest::Breadcrumbs() - */ - protected function updateBadge(&$badgeField) - { - $record = $this->owner->getRecord(); - $badgeField = $this->addFluentBadge($badgeField, $record); - } protected function updateFormActions(FieldList $actions) { diff --git a/src/Extension/FluentLeftAndMainExtension.php b/src/Extension/FluentLeftAndMainExtension.php index c0320cee..5910a62d 100644 --- a/src/Extension/FluentLeftAndMainExtension.php +++ b/src/Extension/FluentLeftAndMainExtension.php @@ -7,11 +7,9 @@ use SilverStripe\Control\HTTPResponse_Exception; use SilverStripe\Core\Extension; use SilverStripe\Forms\Form; -use SilverStripe\Model\List\ArrayList; use SilverStripe\ORM\FieldType\DBHTMLText; use SilverStripe\View\Requirements; use TractorCow\Fluent\Extension\Traits\FluentAdminTrait; -use TractorCow\Fluent\Extension\Traits\FluentBadgeTrait; /** * @extends Extension @@ -19,7 +17,6 @@ class FluentLeftAndMainExtension extends Extension { use FluentAdminTrait; - use FluentBadgeTrait; protected function onInit() { @@ -27,25 +24,6 @@ protected function onInit() Requirements::css("tractorcow/silverstripe-fluent:client/dist/styles/fluent.css"); } - /** - * @param ArrayList $breadcrumbs - * @see CMSMain::Breadcrumbs() - */ - protected function updateBreadcrumbs(ArrayList $breadcrumbs) - { - $record = $this->owner->currentPage(); - if (!$record) { - return; - } - - // Get a possibly existing badge field from the last item in the breadcrumbs list - $lastItem = $breadcrumbs->last(); - $badgeField = $lastItem->hasField('Extra') ? $lastItem->getField('Extra') : null; - $newBadge = $this->addFluentBadge($badgeField, $record); - - $lastItem->setField('Extra', $newBadge); - } - /** * @param Form $form * @param string $message diff --git a/src/Extension/FluentSiteTreeExtension.php b/src/Extension/FluentSiteTreeExtension.php index 196a6b1e..106ed4a7 100644 --- a/src/Extension/FluentSiteTreeExtension.php +++ b/src/Extension/FluentSiteTreeExtension.php @@ -158,33 +158,6 @@ protected function updateLink(&$link, &$action, &$relativeLink) $link = Controller::join_links($domain->Link(), $link); } - /** - * Check whether the current page is exists in the current locale. - * - * If it is invisible then we add a class to show it slightly greyed out in the site tree. - * - * @param array $flags - */ - protected function updateStatusFlags(&$flags) - { - // If there is no current FluentState, then we shouldn't update. - if (!FluentState::singleton()->getLocale()) { - return; - } - - $this->updateModifiedFlag($flags); - $this->updateArchivedFlag($flags); - $this->updateNoSourceFlag($flags); - - // If this page does not exist it should be "invisible" - if (!$this->isDraftedInLocale() && !$this->isPublishedInLocale()) { - $flags['fluentinvisible'] = [ - 'text' => '', - 'title' => '', - ]; - } - } - /** * @param FieldList $fields */ @@ -443,83 +416,6 @@ protected function updateRestoreAction(FieldList $actions): void $actions->removeByName('action_restore'); } - /** - * Update modified flag to reflect localised record instead of base record - * It doesn't make sense to have modified flag if page is not localised in current locale - * - * @param array $flags - */ - protected function updateModifiedFlag(array &$flags): void - { - if (!array_key_exists('modified', $flags)) { - return; - } - - if ($this->owner->isDraftedInLocale()) { - return; - } - - unset($flags['modified']); - } - - /** - * Localise archived flag - remove archived flag if there is content on other locales - * - * @param array $flags - */ - protected function updateArchivedFlag(array &$flags): void - { - if (!array_key_exists('archived', $flags)) { - return; - } - - $locale = FluentState::singleton()->getLocale(); - - if (!$locale) { - return; - } - - if (!$this->owner->getLocaleInstances()) { - return; - } - - unset($flags['archived']); - } - - /** - * Add a flag which indicates that a page has content in other locale but the content is not being inherited - * - * @param array $flags - */ - protected function updateNoSourceFlag(array &$flags): void - { - if (array_key_exists('archived', $flags)) { - return; - } - - $locale = FluentState::singleton()->getLocale(); - - if (!$locale) { - return; - } - - $owner = $this->owner; - $info = $owner->LocaleInformation($locale); - - if ($info->getSourceLocale()) { - return; - } - - if (!$owner->getLocaleInstances()) { - return; - } - - $flags['removedfromdraft'] = [ - 'text' => 'No source', - 'title' => 'This page exists in a different locale but the content is not inherited', - ]; - } - /** * @param Form $form * @param string $message diff --git a/src/Extension/FluentVersionedExtension.php b/src/Extension/FluentVersionedExtension.php index 141556b4..7849e2b5 100644 --- a/src/Extension/FluentVersionedExtension.php +++ b/src/Extension/FluentVersionedExtension.php @@ -586,6 +586,76 @@ public static function prepoulateIdsInLocale($locale, $dataObjectClass, $populat } } + /** + * Check whether the current record is exists in the current locale. + * + * If it is invisible then we add a class to show it slightly greyed out in the site tree. + * + * @param array $flags + */ + protected function updateStatusFlags(array &$flags): void + { + // If there is no current FluentState, then we shouldn't update. + if (!FluentState::singleton()->getLocale()) { + return; + } + + $this->updateModifiedFlag($flags); + $this->updateArchivedFlag($flags); + parent::updateStatusFlags($flags); + + // If this page does not exist it should be "invisible" + if (!$this->isDraftedInLocale() && !$this->isPublishedInLocale()) { + $flags['fluentinvisible'] = [ + 'text' => '', + 'title' => '', + ]; + } + } + + /** + * Update modified flag to reflect localised record instead of base record + * It doesn't make sense to have modified flag if page is not localised in current locale + * + * @param array $flags + */ + protected function updateModifiedFlag(array &$flags): void + { + if (!array_key_exists('modified', $flags)) { + return; + } + + if ($this->owner->isDraftedInLocale()) { + return; + } + + unset($flags['modified']); + } + + /** + * Localise archived flag - remove archived flag if there is content on other locales + * + * @param array $flags + */ + protected function updateArchivedFlag(array &$flags): void + { + if (!array_key_exists('archived', $flags)) { + return; + } + + $locale = FluentState::singleton()->getLocale(); + + if (!$locale) { + return; + } + + if (!$this->owner->getLocaleInstances()) { + return; + } + + unset($flags['archived']); + } + protected function updateLocalisationTabColumns(&$summaryColumns) { $summaryColumns['Status'] = [ diff --git a/tests/php/Extension/FluentBadgeExtensionTest.php b/tests/php/Extension/FluentBadgeExtensionTest.php index be43a165..a16999f4 100644 --- a/tests/php/Extension/FluentBadgeExtensionTest.php +++ b/tests/php/Extension/FluentBadgeExtensionTest.php @@ -2,84 +2,93 @@ namespace TractorCow\Fluent\Tests\Extension; -use SilverStripe\CMS\Model\SiteTree; -use SilverStripe\Control\Controller; use SilverStripe\Dev\SapphireTest; -use SilverStripe\ORM\FieldType\DBHTMLText; -use TractorCow\Fluent\Extension\FluentLeftAndMainExtension; -use TractorCow\Fluent\Extension\FluentSiteTreeExtension; -use TractorCow\Fluent\Model\Locale; +use TractorCow\Fluent\Extension\FluentExtension; use TractorCow\Fluent\State\FluentState; -use TractorCow\Fluent\Tests\Extension\Stub\FluentStubController; +use TractorCow\Fluent\Tests\Extension\Stub\FluentDataObject; class FluentBadgeExtensionTest extends SapphireTest { protected static $fixture_file = 'FluentBadgeExtensionTest.yml'; + protected static $extra_dataobjects = [ + FluentDataObject::class, + ]; + protected static $required_extensions = [ - SiteTree::class => [ - FluentSiteTreeExtension::class, + FluentDataObject::class => [ + FluentExtension::class, ], ]; - /** - * @var SiteTree - */ - protected $mockPage; - - /** - * @var Controller - */ - protected $mockController; - - /** - * @var FluentLeftAndMainExtension - */ - protected $extension; - protected function setUp(): void { parent::setUp(); - - // Clear cache - Locale::clearCached(); - FluentState::singleton()->withState(function (FluentState $newState) { $newState->setLocale('en_NZ'); - - $this->mockPage = $this->objFromFixture(SiteTree::class, 'test_page'); - $this->mockController = new FluentStubController($this->mockPage->ID); - $this->extension = new FluentLeftAndMainExtension(); - $this->extension->setOwner($this->mockController); + $record = $this->objFromFixture(FluentDataObject::class, 'test_record'); + // Ensure the record is written in this locale + $record->write(); }); } + /** + * Tests status flag added for the locale this is saved in + */ public function testDefaultLocaleBadgeAdded() { // Publish the page in the default locale FluentState::singleton()->withState(function (FluentState $newState) { $newState->setLocale('en_NZ'); - $this->mockPage->publishRecursive(); + $record = $this->objFromFixture(FluentDataObject::class, 'test_record'); + $flags = $record->getStatusFlags(); - $result = $this->extension->getBadge($this->mockPage); - $this->assertInstanceOf(DBHTMLText::class, $result); - $this->assertStringContainsString('fluent-badge--default', $result->getValue()); - $this->assertStringContainsString('Localised in', $result->getValue()); - $this->assertStringContainsString('NZ', $result->getValue(), 'Badge shows owner locale'); + $this->assertArrayHasKey('fluent fluent-badge fluent-badge--default', $flags); + $this->assertSame( + ['title' => 'Localised in English (NZ)', 'text' => 'en_NZ'], + $flags['fluent fluent-badge fluent-badge--default'] + ); }); } + /** + * Tests status flag added for the fallback locale + */ + public function testLocalisedLocaleBadgeAdded() + { + // Publish the page in the default locale + FluentState::singleton()->withState(function (FluentState $newState) { + $newState->setLocale('pt_PT'); + $record = $this->objFromFixture(FluentDataObject::class, 'test_record'); + $flags = $record->getStatusFlags(); + + $this->assertArrayHasKey('fluent fluent-badge fluent-badge--localised', $flags); + $this->assertSame( + ['title' => 'Localised in English (NZ)', 'text' => 'en_NZ'], + $flags['fluent fluent-badge fluent-badge--localised'] + ); + }); + } + + /** + * Tests status flag added to indicate this record is NOT saved in this locale + */ public function testInvisibleLocaleBadgeWasAdded() { FluentState::singleton()->withState(function (FluentState $newState) { // Don't write the page in the non-default locale, then it shouldn't exist $newState->setLocale('de_DE'); + $record = $this->objFromFixture(FluentDataObject::class, 'test_record'); + $flags = $record->getStatusFlags(); - $result = $this->extension->getBadge($this->mockPage); - $this->assertInstanceOf(DBHTMLText::class, $result); - $this->assertStringContainsString('fluent-badge--invisible', $result->getValue()); - $this->assertStringContainsString('Page has no available content in', $result->getValue()); - $this->assertStringContainsString('de_DE', $result->getValue(), 'Badge shows owner locale'); + $this->assertArrayHasKey('fluent fluent-badge fluent-badge--invisible', $flags); + $this->assertSame( + [ + 'title' => 'Fluent Data Object has no available content in German, localise the Fluent Data Object or provide a locale fallback', + 'text' => 'de_DE', + ], + $flags['fluent fluent-badge fluent-badge--invisible'] + ); }); } } diff --git a/tests/php/Extension/FluentBadgeExtensionTest.yml b/tests/php/Extension/FluentBadgeExtensionTest.yml index 9f294d50..e29c4ac5 100644 --- a/tests/php/Extension/FluentBadgeExtensionTest.yml +++ b/tests/php/Extension/FluentBadgeExtensionTest.yml @@ -8,9 +8,17 @@ TractorCow\Fluent\Model\Locale: Title: German Locale: de_DE URLSegment: de_DE + pt_PT: + Title: Portuguese + Locale: pt_PT + URLSegment: pt_PT -SilverStripe\CMS\Model\SiteTree: - test_page: +TractorCow\Fluent\Model\FallbackLocale: + en_NZ: + Locale: =>TractorCow\Fluent\Model\Locale.en_NZ + Parent: =>TractorCow\Fluent\Model\Locale.pt_PT + +TractorCow\Fluent\Tests\Extension\Stub\FluentDataObject: + test_record: Title: Test page - URLSegment: test-page - Content: Test content + Description: Test content