Skip to content

Commit

Permalink
FIX: Source locale indicator correction.
Browse files Browse the repository at this point in the history
  • Loading branch information
mfendeksilverstripe committed Apr 9, 2024
1 parent 7bf314a commit fce085f
Show file tree
Hide file tree
Showing 6 changed files with 275 additions and 16 deletions.
36 changes: 25 additions & 11 deletions src/Extension/FluentExtension.php
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@
use SilverStripe\ORM\Queries\SQLConditionGroup;
use SilverStripe\ORM\Queries\SQLSelect;
use SilverStripe\ORM\ValidationException;
use SilverStripe\Security\Permission;
use SilverStripe\Versioned\Versioned;
use SilverStripe\View\HTML;
use TractorCow\Fluent\Extension\Traits\FluentObjectTrait;
Expand Down Expand Up @@ -582,11 +581,11 @@ public function augmentSQL(SQLSelect $query, DataQuery $dataQuery = null)

// Apply substitutions
$localisedPredicate = str_replace($conditionSearch, $conditionReplace, $predicate);

if (empty($localisedPredicate)) {
continue;
}

$where[$index] = [
$localisedPredicate => $parameters
];
Expand Down Expand Up @@ -965,19 +964,24 @@ protected function getRecordLocale()
return Locale::getCurrentLocale();
}


/**
* Returns the source locale that will display the content for this record
*
* @return Locale|null
*/
public function getSourceLocale()
public function getSourceLocale(): ?Locale
{
$sourceLocale = $this->owner->getField('SourceLocale');
if ($sourceLocale) {
return Locale::getByLocale($sourceLocale);
$currentLocale = FluentState::singleton()->getLocale();

// We do not have any locales set up yet, so there is no source locale to find
if (!$currentLocale) {
return null;
}
return Locale::getDefault();

$owner = $this->owner;
$localeInformation = $owner->LocaleInformation($currentLocale);

return $localeInformation->getSourceLocale();
}

/**
Expand Down Expand Up @@ -1265,11 +1269,21 @@ public function updateLocalisationTabColumns(&$summaryColumns)
$summaryColumns['Source'] = [
'title' => 'Source',
'callback' => function (Locale $object) {
if (!$object->RecordLocale()) {
$localeInformation = $object->RecordLocale();

if (!$localeInformation) {
return '';
}

$sourceLocale = $object->RecordLocale()->getSourceLocale();
$sourceLocale = FluentState::singleton()->withState(
static function (FluentState $state) use ($localeInformation): ?Locale {
// We are currently in the CMS context, but we want to show to the content author
// what the data state is in the frontend context
$state->setIsFrontend(true);

return $localeInformation->getSourceLocale();
}
);

if ($sourceLocale) {
return $sourceLocale->getLongTitle();
Expand Down
14 changes: 12 additions & 2 deletions src/Extension/FluentVersionedExtension.php
Original file line number Diff line number Diff line change
Expand Up @@ -616,11 +616,21 @@ public function updateLocalisationTabColumns(&$summaryColumns)
$summaryColumns['Source'] = [
'title' => 'Source',
'callback' => function (Locale $object) {
if (!$object->RecordLocale()) {
$localeInformation = $object->RecordLocale();

if (!$localeInformation) {
return '';
}

$sourceLocale = $object->RecordLocale()->getSourceLocale();
$sourceLocale = FluentState::singleton()->withState(
static function (FluentState $state) use ($localeInformation): ?Locale {
// We are currently in the CMS context, but we want to show to the content author
// what the data state is in the frontend context
$state->setIsFrontend(true);

return $localeInformation->getSourceLocale();
}
);

if ($sourceLocale) {
return $sourceLocale->getLongTitle();
Expand Down
14 changes: 12 additions & 2 deletions src/Extension/Traits/FluentBadgeTrait.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
use TractorCow\Fluent\Extension\FluentFilteredExtension;
use TractorCow\Fluent\Model\Locale;
use TractorCow\Fluent\Model\RecordLocale;
use TractorCow\Fluent\State\FluentState;

trait FluentBadgeTrait
{
Expand Down Expand Up @@ -68,6 +69,15 @@ protected function generateBadgeHTML(
$extraProperties = []
) {
$info = RecordLocale::create($record, $locale);
$sourceLocale = FluentState::singleton()->withState(
static function (FluentState $state) use ($info): ?Locale {
// We are currently in the CMS context, but we want to show to the content author
// what the data state is in the frontend context
$state->setIsFrontend(true);

return $info->getSourceLocale();
}
);

// Build new badge
$badgeClasses = ['badge', 'fluent-badge'];
Expand All @@ -81,14 +91,14 @@ protected function generateBadgeHTML(
'locale' => $locale->getTitle()
]
);
} elseif ($info->getSourceLocale()) {
} elseif ($sourceLocale) {
// If object is inheriting content from another locale show the source
$badgeClasses[] = 'fluent-badge--localised';
$tooltip = _t(
__TRAIT__ . '.BadgeInherited',
'Inherited from {locale}',
[
'locale' => $info->getSourceLocale()->getTitle()
'locale' => $sourceLocale->getTitle()
]
);
} else {
Expand Down
25 changes: 24 additions & 1 deletion src/Model/RecordLocale.php
Original file line number Diff line number Diff line change
Expand Up @@ -276,7 +276,15 @@ public function IsPublished($inLocale = false): bool
// If frontend publishing is not required for localisation,
// we need to check if record is published in the source locale
if (!$inLocale && $record->config()->get('frontend_publish_required') !== FluentExtension::INHERITANCE_MODE_EXACT) {
$sourceLocale = $this->getSourceLocale();
$sourceLocale = FluentState::singleton()->withState(
function (FluentState $state): ?Locale {
// We are currently in the CMS context, but we want to show to the content author
// what the data state is in the frontend context
$state->setIsFrontend(true);

return $this->getSourceLocale();
}
);

if (!$sourceLocale) {
// No source locale available
Expand Down Expand Up @@ -367,16 +375,31 @@ public function getSourceLocale(): ?Locale
{
/** @var DataObject|FluentExtension $record */
$record = $this->getOriginalRecord();
$config = $record->config();

$isFrontend = FluentState::singleton()->getIsFrontend();
$inheritanceMode = $isFrontend
? $config->get('frontend_publish_required')
: $config->get('cms_localisation_required');

// This model has localised data in the current locale so the current locale is also the source locale
if ($record->existsInLocale($this->getLocale())) {
return $this->getLocaleObject();
}

// This model requires localisation so fallback of any kind is not allowed
// hence the content can't come from another locale
// We don't have a source locale for such case
if ($inheritanceMode === FluentExtension::INHERITANCE_MODE_EXACT) {
return null;
}

foreach ($this->getLocaleObject()->Fallbacks() as $fallback) {
if (!$record->existsInLocale($fallback->Locale)) {
continue;
}

// We found a locale to fall back to, so this will be our source locale
return $fallback;
}

Expand Down
189 changes: 189 additions & 0 deletions tests/php/Extension/LocaleInheritanceTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,189 @@
<?php

namespace TractorCow\Fluent\Tests\Extension;

use Page;
use SilverStripe\CMS\Model\SiteTree;
use SilverStripe\Dev\SapphireTest;
use SilverStripe\ORM\ValidationException;
use SilverStripe\Versioned\Versioned;
use TractorCow\Fluent\Extension\FluentExtension;
use TractorCow\Fluent\Extension\FluentSiteTreeExtension;
use TractorCow\Fluent\State\FluentState;

class LocaleInheritanceTest extends SapphireTest
{
protected static $fixture_file = 'LocaleInheritanceTest.yml';

protected static $required_extensions = [
SiteTree::class => [
FluentSiteTreeExtension::class,
],
];

/**
* @param string $cmsInheritanceMode
* @param string $frontendInheritanceMode
* @param bool $frontendContext
* @param string $locale
* @param string|null $expected
* @return void
* @throws ValidationException
* @dataProvider sourceLocaleCasesProvider
*/
public function testGetSourceLocale(
string $cmsInheritanceMode,
string $frontendInheritanceMode,
bool $frontendContext,
string $locale,
?string $expected
): void {
Page::config()
->set('cms_localisation_required', $cmsInheritanceMode)
->set('frontend_publish_required', $frontendInheritanceMode);

Versioned::withVersionedMode(function () use ($frontendContext, $locale, $expected): void {
// Make sure we have the correct stage set
Versioned::set_stage(Versioned::DRAFT);

// Create the page in the default locale
FluentState::singleton()->withState(
function (FluentState $state) use ($frontendContext, $locale, $expected): void {
$state
->setLocale('en_US')
->setIsFrontend($frontendContext);

/** @var Page|FluentExtension $page */
$page = Page::create();
$page->Title = 'Page title';
$page->URLSegment = 'test-page';
$page->write();

$localeInformation = $page->LocaleInformation($locale);
$sourceLocaleObject = $localeInformation->getSourceLocale();
$sourceLocale = $sourceLocaleObject?->Locale;
$this->assertEquals(
$expected,
$sourceLocale,
'We expect a specific source locale (locale information)'
);

if (!$sourceLocale) {
return;
}

// Re-fetch the page in the target locale
$state->setLocale($locale);

/** @var Page|FluentExtension $page */
$page = Page::get()->byID($page->ID);

$this->assertNotNull($page, 'We expect the page to be available in this locale');
$sourceLocaleObject = $page->getSourceLocale();
$this->assertEquals(
$expected,
$sourceLocaleObject->Locale,
'We expect a specific source locale (page shorthand method)'
);
}
);
});
}

public function sourceLocaleCasesProvider(): array
{
return [
'default locale, cms with any mode, frontend with any mode, frontend context' => [
FluentExtension::INHERITANCE_MODE_ANY,
FluentExtension::INHERITANCE_MODE_ANY,
true,
'en_US',
'en_US',
],
'default locale, cms with exact mode, frontend with any mode, frontend context' => [
FluentExtension::INHERITANCE_MODE_EXACT,
FluentExtension::INHERITANCE_MODE_ANY,
true,
'en_US',
'en_US',
],
'default locale, cms with any mode, frontend with exact mode, frontend context' => [
FluentExtension::INHERITANCE_MODE_ANY,
FluentExtension::INHERITANCE_MODE_EXACT,
true,
'en_US',
'en_US',
],
'fallback locale, cms with any mode, frontend with any mode, frontend context' => [
FluentExtension::INHERITANCE_MODE_ANY,
FluentExtension::INHERITANCE_MODE_ANY,
true,
'de_DE',
'en_US',
],
'fallback locale, cms with exact mode, frontend with any mode, frontend context' => [
FluentExtension::INHERITANCE_MODE_EXACT,
FluentExtension::INHERITANCE_MODE_ANY,
true,
'de_DE',
'en_US',
],
'fallback locale, cms with any mode, frontend with exact mode, frontend context' => [
FluentExtension::INHERITANCE_MODE_ANY,
FluentExtension::INHERITANCE_MODE_EXACT,
true,
'de_DE',
null,
],
'fallback locale, cms with any mode, frontend with fallback mode, frontend context' => [
FluentExtension::INHERITANCE_MODE_ANY,
FluentExtension::INHERITANCE_MODE_FALLBACK,
true,
'de_DE',
'en_US',
],
'fallback locale, cms with any mode, frontend with exact mode, cms context' => [
FluentExtension::INHERITANCE_MODE_ANY,
FluentExtension::INHERITANCE_MODE_EXACT,
false,
'de_DE',
'en_US',
],
'no fallback locale, cms with any mode, frontend with any mode, frontend context' => [
FluentExtension::INHERITANCE_MODE_ANY,
FluentExtension::INHERITANCE_MODE_ANY,
true,
'es_ES',
null,
],
'no fallback locale, cms with exact mode, frontend with any mode, frontend context' => [
FluentExtension::INHERITANCE_MODE_EXACT,
FluentExtension::INHERITANCE_MODE_ANY,
true,
'es_ES',
null,
],
'no fallback locale, cms with any mode, frontend with exact mode, frontend context' => [
FluentExtension::INHERITANCE_MODE_ANY,
FluentExtension::INHERITANCE_MODE_EXACT,
true,
'es_ES',
null,
],
'no fallback locale, cms with any mode, frontend with fallback mode, frontend context' => [
FluentExtension::INHERITANCE_MODE_ANY,
FluentExtension::INHERITANCE_MODE_FALLBACK,
true,
'es_ES',
null,
],
'no fallback locale, cms with any mode, frontend with exact mode, cms context' => [
FluentExtension::INHERITANCE_MODE_ANY,
FluentExtension::INHERITANCE_MODE_EXACT,
false,
'es_ES',
null,
],
];
}
}
13 changes: 13 additions & 0 deletions tests/php/Extension/LocaleInheritanceTest.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
TractorCow\Fluent\Model\Locale:
default:
Title: US English
Locale: en_US
IsGlobalDefault: true
german:
Title: German
Locale: de_DE
Fallbacks:
- =>TractorCow\Fluent\Model\Locale.default
spanish:
Title: Spanish
Locale: es_ES

0 comments on commit fce085f

Please sign in to comment.