diff --git a/src/Extension/FluentExtension.php b/src/Extension/FluentExtension.php index 575c100a..627f0fcb 100644 --- a/src/Extension/FluentExtension.php +++ b/src/Extension/FluentExtension.php @@ -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 * @@ -975,7 +989,7 @@ public function getSourceLocale(): ?Locale $owner = $this->owner; $currentLocale = FluentState::singleton()->getLocale(); - // We do not have a locale set, so we can't determine a source + // We do not have a locale set, so we can't determine the source locale if (!$currentLocale) { return null; } diff --git a/src/Model/RecordLocale.php b/src/Model/RecordLocale.php index 4374727c..fd95695c 100644 --- a/src/Model/RecordLocale.php +++ b/src/Model/RecordLocale.php @@ -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; @@ -367,19 +369,80 @@ public function getSourceLocale(): ?Locale { /** @var DataObject|FluentExtension $record */ $record = $this->getOriginalRecord(); + $config = $record->config(); + $inheritanceMode = FluentState::singleton()->getIsFrontend() + ? $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; + } + + $fallbackLocales = []; + foreach ($this->getLocaleObject()->Fallbacks() as $fallback) { - if (!$record->existsInLocale($fallback->Locale)) { + $fallbackLocale = $fallback->Locale; + $fallbackLocales[] = $fallbackLocale; + + if (!$record->existsInLocale($fallbackLocale)) { continue; } + // We found a locale to fall back to, so this will be our source locale return $fallback; } + // 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 + if ($inheritanceMode === FluentExtension::INHERITANCE_MODE_ANY) { + $lastEditedList = ArrayList::create(); + + /** @var RecordLocale $localeInformation */ + foreach ($record->Locales() as $localeInformation) { + $locale = $localeInformation->getLocale(); + + // Ignore any fallback locales as we've already confirmed that none of these locales + // are acting as the source locale + if (in_array($locale, $fallbackLocales)) { + continue; + } + + $localisedRecord = $localeInformation->getRecord(); + + // We don't have any localised data in this locale so this doesn't qualify as a potential source locale + if (!$localisedRecord) { + continue; + } + + $data = ArrayData::create([ + 'Locale' => $locale, + 'LastEdited' => $localisedRecord->LastEdited, + ]); + + $lastEditedList->push($data); + } + + // We found at leadt one candidate for the source locale, let's pick the most recently updated one + if ($lastEditedList->count() > 0) { + $sortedLocales = $lastEditedList + ->sort('LastEdited', 'DESC') + ->column('Locale'); + $mostRecentlyEditedLocale = array_shift($sortedLocales); + + return Locale::getByLocale($mostRecentlyEditedLocale); + } + } + return null; } }