diff --git a/src/Extension/FluentExtension.php b/src/Extension/FluentExtension.php index ff4f6820..f92fd51c 100644 --- a/src/Extension/FluentExtension.php +++ b/src/Extension/FluentExtension.php @@ -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; @@ -48,6 +47,7 @@ * * @template T of DataObject * @extends DataExtension + * @property DataObject|$this $owner */ class FluentExtension extends DataExtension { @@ -85,6 +85,22 @@ class FluentExtension extends DataExtension */ const INHERITANCE_MODE_ANY = 'any'; + /** + * Fluent inheritance mode for frontend context + * + * @var string + * @config + */ + private static string $frontend_publish_required = self::INHERITANCE_MODE_ANY; + + /** + * Fluent inheritance mode for CMS context + * + * @var string + * @config + */ + 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 * @@ -582,11 +598,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 ]; diff --git a/src/Extension/FluentFilteredExtension.php b/src/Extension/FluentFilteredExtension.php index b7dac66c..d1e5d75a 100644 --- a/src/Extension/FluentFilteredExtension.php +++ b/src/Extension/FluentFilteredExtension.php @@ -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, ]; diff --git a/tests/php/Extension/FluentFilteredExtensionTest.php b/tests/php/Extension/FluentFilteredExtensionTest.php index 17b5eacf..d6bcd49c 100644 --- a/tests/php/Extension/FluentFilteredExtensionTest.php +++ b/tests/php/Extension/FluentFilteredExtensionTest.php @@ -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; @@ -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); @@ -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); @@ -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); diff --git a/tests/php/Extension/FluentSiteTreeExtensionTest.php b/tests/php/Extension/FluentSiteTreeExtensionTest.php index aa0e1d97..1878e994 100644 --- a/tests/php/Extension/FluentSiteTreeExtensionTest.php +++ b/tests/php/Extension/FluentSiteTreeExtensionTest.php @@ -10,10 +10,8 @@ use SilverStripe\Core\Config\Config; use SilverStripe\Dev\SapphireTest; use SilverStripe\Forms\CompositeField; -use SilverStripe\Forms\FieldList; use SilverStripe\Forms\LiteralField; use SilverStripe\ORM\ArrayList; -use SilverStripe\ORM\DataObject; use SilverStripe\ORM\ValidationException; use SilverStripe\Versioned\Versioned; use TractorCow\Fluent\Extension\FluentDirectorExtension; @@ -334,140 +332,94 @@ function (FluentState $newState) use ($localeCode, $fixture, $expected) { ); } - public function testHomeVisibleOnFrontendBothConfigAny() - { - Config::modify()->set(DataObject::class, 'cms_localisation_required', FluentExtension::INHERITANCE_MODE_ANY); - Config::modify()->set(DataObject::class, 'frontend_publish_required', FluentExtension::INHERITANCE_MODE_ANY); - - FluentState::singleton()->withState(function (FluentState $newState) { - $newState - ->setLocale('de_DE') - ->setIsDomainMode(false) - ->setIsFrontend(true); - - $page = Page::get()->filter('URLSegment', 'home')->first(); - - $this->assertNotNull($page); - }); - } - - public function testHomeVisibleOnFrontendOneConfigAny() - { - Config::modify()->set(DataObject::class, 'cms_localisation_required', FluentExtension::INHERITANCE_MODE_EXACT); - Config::modify()->set(DataObject::class, 'frontend_publish_required', FluentExtension::INHERITANCE_MODE_ANY); - - FluentState::singleton()->withState(function (FluentState $newState) { - $newState - ->setLocale('de_DE') - ->setIsDomainMode(false) - ->setIsFrontend(true); - - $page = Page::get()->filter('URLSegment', 'home')->first(); - - $this->assertNotNull($page); - }); - } - - public function testHomeNotVisibleOnFrontendBothConfigExact() - { - Config::modify()->set(DataObject::class, 'cms_localisation_required', FluentExtension::INHERITANCE_MODE_EXACT); - Config::modify()->set(DataObject::class, 'frontend_publish_required', FluentExtension::INHERITANCE_MODE_EXACT); - - FluentState::singleton()->withState(function (FluentState $newState) { - $newState - ->setLocale('de_DE') - ->setIsDomainMode(false) - ->setIsFrontend(true); - - $page = Page::get()->filter('URLSegment', 'home')->first(); - - $this->assertNull($page); - }); - } - - public function testHomeNotVisibleOnFrontendOneConfigExact() - { - Config::modify()->set(DataObject::class, 'cms_localisation_required', FluentExtension::INHERITANCE_MODE_ANY); - Config::modify()->set(DataObject::class, 'frontend_publish_required', FluentExtension::INHERITANCE_MODE_EXACT); - - FluentState::singleton()->withState(function (FluentState $newState) { - $newState - ->setLocale('de_DE') - ->setIsDomainMode(false) - ->setIsFrontend(true); - - $page = Page::get()->filter('URLSegment', 'home')->first(); - - $this->assertNull($page); - }); - } - - public function testHomeVisibleInCMSBothConfigAny() - { - Config::modify()->set(DataObject::class, 'cms_localisation_required', FluentExtension::INHERITANCE_MODE_ANY); - Config::modify()->set(DataObject::class, 'frontend_publish_required', FluentExtension::INHERITANCE_MODE_ANY); - - FluentState::singleton()->withState(function (FluentState $newState) { - $newState - ->setLocale('de_DE') - ->setIsDomainMode(false) - ->setIsFrontend(false); - - $page = Page::get()->filter('URLSegment', 'home')->first(); - - $this->assertNotNull($page); - }); - } - - public function testHomeVisibleInCMSOneConfigAny() - { - Config::modify()->set(DataObject::class, 'cms_localisation_required', FluentExtension::INHERITANCE_MODE_ANY); - Config::modify()->set(DataObject::class, 'frontend_publish_required', FluentExtension::INHERITANCE_MODE_EXACT); - - FluentState::singleton()->withState(function (FluentState $newState) { - $newState + /** + * @param string $cmsInheritanceMode + * @param string $frontendInheritanceMode + * @param bool $frontendContext + * @param bool $expected + * @return void + * @dataProvider localeInheritanceModeCasesProvider + */ + public function testLocaleInheritanceMode( + string $cmsInheritanceMode, + string $frontendInheritanceMode, + bool $frontendContext, + bool $expected + ): void { + Page::config() + ->set('cms_localisation_required', $cmsInheritanceMode) + ->set('frontend_publish_required', $frontendInheritanceMode); + + FluentState::singleton()->withState(function (FluentState $state) use ($frontendContext, $expected) { + $state ->setLocale('de_DE') ->setIsDomainMode(false) - ->setIsFrontend(false); + ->setIsFrontend($frontendContext); - $page = Page::get()->filter('URLSegment', 'home')->first(); + $page = Page::get()->find('URLSegment', 'home'); - $this->assertNotNull($page); - }); - } - - public function testHomeNotVisibleInCMSBothConfigExact() - { - Config::modify()->set(DataObject::class, 'cms_localisation_required', FluentExtension::INHERITANCE_MODE_EXACT); - Config::modify()->set(DataObject::class, 'frontend_publish_required', FluentExtension::INHERITANCE_MODE_EXACT); + if ($expected) { + $this->assertNotNull($page, 'We expect the page model to have content available'); - FluentState::singleton()->withState(function (FluentState $newState) { - $newState - ->setLocale('de_DE') - ->setIsDomainMode(false) - ->setIsFrontend(false); - - $page = Page::get()->filter('URLSegment', 'home')->first(); + return; + } - $this->assertNull($page); + $this->assertNull($page, 'We expect the page model to not have any content available'); }); } - public function testHomeNotVisibleInCMSOneConfigExact() + public function localeInheritanceModeCasesProvider(): array { - Config::modify()->set(DataObject::class, 'cms_localisation_required', FluentExtension::INHERITANCE_MODE_EXACT); - Config::modify()->set(DataObject::class, 'frontend_publish_required', FluentExtension::INHERITANCE_MODE_ANY); - - FluentState::singleton()->withState(function (FluentState $newState) { - $newState - ->setLocale('de_DE') - ->setIsDomainMode(false) - ->setIsFrontend(false); - - $page = Page::get()->filter('URLSegment', 'home')->first(); - - $this->assertNull($page); - }); + return [ + 'cms with any mode, frontend with any mode, frontend context' => [ + FluentExtension::INHERITANCE_MODE_ANY, + FluentExtension::INHERITANCE_MODE_ANY, + true, + true, + ], + 'cms with exact mode, frontend with any mode, frontend context' => [ + FluentExtension::INHERITANCE_MODE_EXACT, + FluentExtension::INHERITANCE_MODE_ANY, + true, + true, + ], + 'cms with exact mode, frontend with exact mode, frontend context' => [ + FluentExtension::INHERITANCE_MODE_EXACT, + FluentExtension::INHERITANCE_MODE_EXACT, + true, + false, + ], + 'cms with any mode, frontend with exact mode, frontend context' => [ + FluentExtension::INHERITANCE_MODE_ANY, + FluentExtension::INHERITANCE_MODE_EXACT, + true, + false, + ], + 'cms with any mode, frontend with any mode, cms context' => [ + FluentExtension::INHERITANCE_MODE_ANY, + FluentExtension::INHERITANCE_MODE_ANY, + false, + true, + ], + 'cms with any mode, frontend with exact mode, cms context' => [ + FluentExtension::INHERITANCE_MODE_ANY, + FluentExtension::INHERITANCE_MODE_EXACT, + false, + true, + ], + 'cms with exact mode, frontend with exact mode, cms context' => [ + FluentExtension::INHERITANCE_MODE_EXACT, + FluentExtension::INHERITANCE_MODE_EXACT, + false, + false, + ], + 'cms with exact mode, frontend with any mode, cms context' => [ + FluentExtension::INHERITANCE_MODE_EXACT, + FluentExtension::INHERITANCE_MODE_ANY, + false, + false, + ], + ]; } /** @@ -490,11 +442,15 @@ public function localePrefixUrlProvider() * @throws ValidationException * @dataProvider localeFallbackProvider */ - public function testPageVisibilityWithFallback($cmsMode, $frontendMode, bool $isFrontend, int $expected) - { - Config::modify() - ->set(DataObject::class, 'cms_localisation_required', $cmsMode) - ->set(DataObject::class, 'frontend_publish_required', $frontendMode); + public function testPageVisibilityWithFallback( + string|bool $cmsMode, + string|bool $frontendMode, + bool $isFrontend, + int $expected + ): void { + Page::config() + ->set('cms_localisation_required', $cmsMode) + ->set('frontend_publish_required', $frontendMode); $pageId = FluentState::singleton()->withState(function (FluentState $state): int { $state diff --git a/tests/php/Extension/FluentVersionedExtensionTest.php b/tests/php/Extension/FluentVersionedExtensionTest.php index 44e97905..7ab3986e 100644 --- a/tests/php/Extension/FluentVersionedExtensionTest.php +++ b/tests/php/Extension/FluentVersionedExtensionTest.php @@ -102,7 +102,7 @@ public function testSourceLocaleIsCurrentWhenPageExistsInIt() ->setIsDomainMode(false); // Read from the locale that the page exists in already - /** @var Page $page */ + /** @var Page|FluentSiteTreeExtension $page */ $page = $this->objFromFixture(Page::class, 'home'); $this->assertEquals('en_NZ', $page->getSourceLocale()->Locale);