diff --git a/_build/test/Tests/Model/modXSwitchContextCultureTest.php b/_build/test/Tests/Model/modXSwitchContextCultureTest.php new file mode 100644 index 0000000000..cca501e36b --- /dev/null +++ b/_build/test/Tests/Model/modXSwitchContextCultureTest.php @@ -0,0 +1,83 @@ +modx->context; + $this->modx->context = null; + try { + $this->assertFalse($this->modx->switchContext('web')); + } finally { + $this->modx->context = $previous; + } + } + + public function testSwitchContextReinitializesCultureKey() + { + $originalKey = $this->modx->context->get('key'); + $targetKey = ($originalKey === 'web') ? 'mgr' : 'web'; + + $setting = $this->modx->getObject(modContextSetting::class, [ + 'context_key' => $targetKey, + 'key' => 'cultureKey', + ]); + $created = false; + if (!$setting) { + $setting = $this->modx->newObject(modContextSetting::class); + $setting->fromArray([ + 'context_key' => $targetKey, + 'key' => 'cultureKey', + 'value' => 'de', + 'xtype' => 'textfield', + 'namespace' => 'core', + 'area' => 'language', + ], '', true); + $this->assertTrue((bool)$setting->save()); + $created = true; + } + $previousValue = $setting->get('value'); + $setting->set('value', 'de'); + $setting->save(); + + // Avoid session/request overrides masking the context cultureKey. + unset($_SESSION['cultureKey'], $_REQUEST['cultureKey']); + + try { + $switched = $this->modx->switchContext($targetKey, true); + $this->assertTrue($switched, 'Expected switchContext to succeed'); + $this->assertSame('de', $this->modx->cultureKey); + $this->assertSame('de', $this->modx->getOption('cultureKey')); + } finally { + $this->modx->switchContext($originalKey, true); + if ($created) { + $setting->remove(); + } else { + $setting->set('value', $previousValue); + $setting->save(); + } + } + } +} diff --git a/_build/test/phpunit.xml b/_build/test/phpunit.xml index 6eba756c6c..0ebdf0fa4d 100644 --- a/_build/test/phpunit.xml +++ b/_build/test/phpunit.xml @@ -18,6 +18,7 @@ Tests/Model/modXTest.php + Tests/Model/modXSwitchContextCultureTest.php Tests/Model/modXLoggingTest.php Tests/Model/modParserTest.php Tests/Model/Dashboard diff --git a/core/src/Revolution/modX.php b/core/src/Revolution/modX.php index c2307d0f39..65ed96a311 100644 --- a/core/src/Revolution/modX.php +++ b/core/src/Revolution/modX.php @@ -2133,14 +2133,25 @@ public function addEventListener($event, $pluginId, $propertySetName = '') { * before being switched to. * @return boolean True if the switch was successful, otherwise false. */ - public function switchContext($contextKey, $reload = false) { - $switched= false; + public function switchContext($contextKey, $reload = false) + { + $switched = false; + if ($this->context === null) { + return $switched; + } if ($this->context->key != $contextKey) { - $switched= $this->_initContext($contextKey, $reload); + $switched = $this->_initContext($contextKey, $reload); if ($switched) { if (is_array($this->config)) { $this->setPlaceholders($this->config, '+'); } + /* + * Reconcile session/culture for the new context options without + * exposing public initSession/initCulture (see #14962 / opengeek). + * _initSession is a no-op when a session is already active. + */ + $this->_initSession(null); + $this->_initCulture(null); } } return $switched;