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 8, 2024
1 parent 7bf314a commit bc6bbbd
Show file tree
Hide file tree
Showing 8 changed files with 372 additions and 151 deletions.
40 changes: 33 additions & 7 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 All @@ -48,6 +47,7 @@
*
* @template T of DataObject
* @extends DataExtension<T&static>
* @property DataObject|$this $owner
*/
class FluentExtension extends DataExtension
{
Expand Down Expand Up @@ -85,6 +85,20 @@ class FluentExtension extends DataExtension
*/
const INHERITANCE_MODE_ANY = 'any';

/**
* Fluent inheritance mode for frontend
*
* @var string
*/
private static string $frontend_publish_required = self::INHERITANCE_MODE_ANY;

/**
* Fluent inheritance mode for CMS
*
* @var string
*/
private static string $cms_localisation_required = self::INHERITANCE_MODE_ANY;

/**
* DB fields to be used added in when creating a localised version of the owner's table
*
Expand Down Expand Up @@ -582,11 +596,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 +979,31 @@ protected function getRecordLocale()
return Locale::getCurrentLocale();
}


/**
* Returns the source locale that will display the content for this record
* Source locale for frontend context is used by default as this is the most common use,
* but you can optionally specify CMS context as well
* Passing null will fall back to whatever context is currently in use
*
* @param bool|null $isFrontend
* @return Locale|null
*/
public function getSourceLocale()
public function getSourceLocale(?bool $isFrontend = true): ?Locale
{
$sourceLocale = $this->owner->getField('SourceLocale');
$owner = $this->owner;
$currentLocale = FluentState::singleton()->getLocale();

// We do not have a locale set, so we can't determine the source locale
if (!$currentLocale) {
return null;
}

$localeInformation = $owner->LocaleInformation($currentLocale);
$sourceLocale = $localeInformation->getSourceLocale($isFrontend);
if ($sourceLocale) {
return Locale::getByLocale($sourceLocale);
}
return Locale::getDefault();
return null;
}

/**
Expand Down
8 changes: 8 additions & 0 deletions src/Extension/FluentFilteredExtension.php
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,14 @@ class FluentFilteredExtension extends DataExtension
*/
const SUFFIX = 'FilteredLocales';

/**
* Allow the filtered locale behaviour to be skipped for draft stage only
*
* @var bool
* @config
*/
private static bool $apply_filtered_locales_to_stage = false;

private static $many_many = [
'FilteredLocales' => Locale::class,
];
Expand Down
33 changes: 32 additions & 1 deletion src/Model/RecordLocale.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,10 @@

use SilverStripe\Control\Director;
use SilverStripe\i18n\i18n;
use SilverStripe\ORM\ArrayList;
use SilverStripe\ORM\DataObject;
use SilverStripe\Versioned\Versioned;
use SilverStripe\View\ArrayData;
use SilverStripe\View\ViewableData;
use TractorCow\Fluent\Extension\FluentExtension;
use TractorCow\Fluent\Extension\FluentFilteredExtension;
Expand Down Expand Up @@ -360,26 +362,55 @@ public function getStagesDiffer(): bool

/**
* Get the locale which is the source of content for this record
* Source locale for frontend context is used by default as this is the most common use,
* but you can optionally specify CMS context as well
* Passing null will fall back to whatever context is currently in use
*
* @param bool|null $isFrontend
* @return Locale|null
*/
public function getSourceLocale(): ?Locale
public function getSourceLocale(?bool $isFrontend = true): ?Locale
{
$isFrontendFromState = FluentState::singleton()->getIsFrontend();
$isFrontend ??= $isFrontendFromState;

/** @var DataObject|FluentExtension $record */
$record = $this->getOriginalRecord();
$config = $record->config();

$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 this 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;
}

// Noting here that we have another case here that isn't handled correctly
// In case this model allows fallback to any locale even bypassing the fallback rules,
// so we just need to find the most recently updated locale
// as that's the one which is going to be providing content
// This is what we call base record fallback
// It's technically possible to figure out which locale the content is coming from but
// displaying this information may actually be confusing so just displaying no source might be more helpful

return null;
}
}
20 changes: 9 additions & 11 deletions tests/php/Extension/FluentFilteredExtensionTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,8 @@

use Page;
use SilverStripe\CMS\Model\SiteTree;
use SilverStripe\Core\Config\Config;
use SilverStripe\Dev\SapphireTest;
use SilverStripe\Forms\GridField\GridField;
use SilverStripe\ORM\DataObject;
use SilverStripe\Versioned\Versioned;
use TractorCow\Fluent\Extension\FluentFilteredExtension;
use TractorCow\Fluent\Extension\FluentSiteTreeExtension;
Expand Down Expand Up @@ -44,14 +42,14 @@ protected function setUp(): void
public function testAugmentSQLFrontend()
{
// Specifically set this config value so that filtered locales ARE required in stage=Stage.
Config::modify()->set(DataObject::class, 'apply_filtered_locales_to_stage', true);
SiteTree::config()->set('apply_filtered_locales_to_stage', true);

$currentStage = Versioned::get_stage();

Versioned::set_stage(Versioned::DRAFT);

FluentState::singleton()->withState(function (FluentState $newState) {
$newState
FluentState::singleton()->withState(function (FluentState $state) {
$state
->setLocale('en_NZ')
->setIsFrontend(true)
->setIsDomainMode(false);
Expand All @@ -72,14 +70,14 @@ public function testAugmentSQLFrontend()
public function testAugmentSQLFrontendLive()
{
// Specifically set this config value so that filtered locales ARE required in stage=Stage.
Config::modify()->set(DataObject::class, 'apply_filtered_locales_to_stage', true);
SiteTree::config()->set('apply_filtered_locales_to_stage', true);

$currentStage = Versioned::get_stage();

Versioned::set_stage(Versioned::LIVE);

FluentState::singleton()->withState(function (FluentState $newState) {
$newState
FluentState::singleton()->withState(function (FluentState $state) {
$state
->setLocale('en_NZ')
->setIsFrontend(true);

Expand All @@ -99,15 +97,15 @@ public function testAugmentSQLFrontendLive()
public function testAugmentSQLStage()
{
// Specifically set this config value so that filtered locales are NOT required in stage=Stage.
Config::modify()->set(DataObject::class, 'apply_filtered_locales_to_stage', false);
SiteTree::config()->set('apply_filtered_locales_to_stage', false);

$currentStage = Versioned::get_stage();

Versioned::set_stage(Versioned::DRAFT);

// Run test
FluentState::singleton()->withState(function (FluentState $newState) {
$newState
FluentState::singleton()->withState(function (FluentState $state) {
$state
->setLocale('en_NZ')
->setIsFrontend(true);

Expand Down
Loading

0 comments on commit bc6bbbd

Please sign in to comment.