diff --git a/composer.json b/composer.json index 9a2320a..2011d1e 100644 --- a/composer.json +++ b/composer.json @@ -5,15 +5,26 @@ "license": "proprietary", "require": { "php": ">=7.1", - "spryker/kernel": "^3.0.0" + "spryker/application-extension": "^1.0.0", + "spryker/event-dispatcher-extension": "^1.0.0", + "spryker/kernel": "^3.0.0", + "spryker/locale-extension": "^1.0.0" }, "require-dev": { + "spryker/config": "*", + "spryker/container": "*", + "spryker/event-dispatcher": "*", "spryker/installer": "*", "spryker/propel": "*", + "spryker/symfony": "*", "spryker/testify": "*" }, "suggest": { - "spryker/installer": "If you want to use Installer plugins." + "spryker/config": "If you want to use LocaleApplicationPlugin", + "spryker/container": "If you want to use LocalePlugin.", + "spryker/event-dispatcher": "If you want to use EventDispatcher plugin.", + "spryker/installer": "If you want to use Installer plugins.", + "spryker/symfony": "If you want to use EventDispatcher plugin." }, "autoload": { "psr-4": { diff --git a/src/Spryker/Yves/Locale/LocaleDependencyProvider.php b/src/Spryker/Yves/Locale/LocaleDependencyProvider.php new file mode 100644 index 0000000..c558508 --- /dev/null +++ b/src/Spryker/Yves/Locale/LocaleDependencyProvider.php @@ -0,0 +1,77 @@ +addLocalePlugin($container); + $container = $this->addStore($container); + + return $container; + } + + /** + * @param \Spryker\Yves\Kernel\Container $container + * + * @return \Spryker\Yves\Kernel\Container + */ + public function addLocalePlugin(Container $container): Container + { + $container->set(static::PLUGIN_LOCALE, function () { + return $this->getLocalePlugin(); + }); + + return $container; + } + + /** + * @return \Spryker\Shared\LocaleExtension\Dependency\Plugin\LocalePluginInterface + */ + public function getLocalePlugin(): LocalePluginInterface + { + return new LocaleLocalePlugin(); + } + + /** + * @param \Spryker\Yves\Kernel\Container $container + * + * @return \Spryker\Yves\Kernel\Container + */ + public function addStore(Container $container): Container + { + $container->set(static::STORE, function () { + return $this->getStore(); + }); + + return $container; + } + + /** + * @return \Spryker\Shared\Kernel\Store + */ + public function getStore(): Store + { + return Store::getInstance(); + } +} diff --git a/src/Spryker/Yves/Locale/LocaleFactory.php b/src/Spryker/Yves/Locale/LocaleFactory.php new file mode 100644 index 0000000..03ba36e --- /dev/null +++ b/src/Spryker/Yves/Locale/LocaleFactory.php @@ -0,0 +1,31 @@ +getProvidedDependency(LocaleDependencyProvider::PLUGIN_LOCALE); + } + + /** + * @return \Spryker\Shared\Kernel\Store + */ + public function getStore(): Store + { + return $this->getProvidedDependency(LocaleDependencyProvider::STORE); + } +} diff --git a/src/Spryker/Yves/Locale/Plugin/Application/LocaleApplicationPlugin.php b/src/Spryker/Yves/Locale/Plugin/Application/LocaleApplicationPlugin.php new file mode 100644 index 0000000..3a8ef55 --- /dev/null +++ b/src/Spryker/Yves/Locale/Plugin/Application/LocaleApplicationPlugin.php @@ -0,0 +1,72 @@ +addLocale($container); + + return $container; + } + + /** + * @param \Spryker\Service\Container\ContainerInterface $container + * + * @return \Spryker\Service\Container\ContainerInterface + */ + protected function addLocale(ContainerInterface $container): ContainerInterface + { + $container->set(static::BC_FEATURE_FLAG_LOCALE_LISTENER, false); + $container->set(static::SERVICE_LOCALE, function (ContainerInterface $container) { + $localeName = $this->getLocaleTransfer($container)->getLocaleName(); + $this->getFactory()->getStore()->setCurrentLocale($localeName); + ApplicationEnvironment::initializeLocale($localeName); + + return $localeName; + }); + + return $container; + } + + /** + * @param \Spryker\Service\Container\ContainerInterface $container + * + * @return \Generated\Shared\Transfer\LocaleTransfer + */ + protected function getLocaleTransfer(ContainerInterface $container): LocaleTransfer + { + return $this->getFactory()->getLocalePlugin()->getLocaleTransfer($container); + } +} diff --git a/src/Spryker/Yves/Locale/Plugin/EventDispatcher/LocaleEventDispatcherPlugin.php b/src/Spryker/Yves/Locale/Plugin/EventDispatcher/LocaleEventDispatcherPlugin.php new file mode 100644 index 0000000..b9fa4d3 --- /dev/null +++ b/src/Spryker/Yves/Locale/Plugin/EventDispatcher/LocaleEventDispatcherPlugin.php @@ -0,0 +1,74 @@ +addListener( + KernelEvents::REQUEST, + function (GetResponseEvent $event) use ($container) { + $request = $event->getRequest(); + $request->setDefaultLocale($this->getLocaleFromContainer($container)); + + $this->setRequestLocale($request); + }, + static::EVENT_PRIORITY + ); + + return $eventDispatcher; + } + + /** + * @param \Symfony\Component\HttpFoundation\Request $request + * + * @return \Symfony\Component\HttpFoundation\Request + */ + protected function setRequestLocale(Request $request): Request + { + $locale = $request->attributes->get('_locale'); + if ($locale) { + $request->setLocale($locale); + } + + return $request; + } + + /** + * @param \Spryker\Service\Container\ContainerInterface $container + * + * @return string + */ + protected function getLocaleFromContainer(ContainerInterface $container): string + { + return $container->get(static::SERVICE_LOCALE); + } +} diff --git a/src/Spryker/Yves/Locale/Plugin/Locale/LocaleLocalePlugin.php b/src/Spryker/Yves/Locale/Plugin/Locale/LocaleLocalePlugin.php new file mode 100644 index 0000000..d2d9b41 --- /dev/null +++ b/src/Spryker/Yves/Locale/Plugin/Locale/LocaleLocalePlugin.php @@ -0,0 +1,91 @@ +buildLocaleTransfer(); + } + + /** + * @return \Generated\Shared\Transfer\LocaleTransfer + */ + protected function buildLocaleTransfer(): LocaleTransfer + { + $localeTransfer = new LocaleTransfer(); + $localeTransfer->setLocaleName($this->getLocaleName()); + + return $localeTransfer; + } + + /** + * @return string + */ + protected function getLocaleName(): string + { + $currentLocale = $this->getClient()->getCurrentLocale(); + + $requestUri = $this->getRequestUri(); + + if ($requestUri) { + $locales = $this->getFactory()->getStore()->getLocales(); + $localeCode = $this->extractLocaleCode($requestUri); + if ($localeCode !== false && isset($locales[$localeCode])) { + return $locales[$localeCode]; + } + } + + return $currentLocale; + } + + /** + * @return string|null + */ + protected function getRequestUri(): ?string + { + $requestUri = Request::createFromGlobals() + ->server->get(static::REQUEST_URI); + + return $requestUri; + } + + /** + * @param string $requestUri + * + * @return string + */ + protected function extractLocaleCode(string $requestUri): string + { + $pathElements = explode('/', trim($requestUri, '/')); + + return $pathElements[0]; + } +} diff --git a/src/Spryker/Zed/Locale/Business/LocaleBusinessFactory.php b/src/Spryker/Zed/Locale/Business/LocaleBusinessFactory.php index ef5c3a8..df87844 100644 --- a/src/Spryker/Zed/Locale/Business/LocaleBusinessFactory.php +++ b/src/Spryker/Zed/Locale/Business/LocaleBusinessFactory.php @@ -7,9 +7,11 @@ namespace Spryker\Zed\Locale\Business; +use Spryker\Shared\Kernel\Store; use Spryker\Zed\Kernel\Business\AbstractBusinessFactory; use Spryker\Zed\Locale\Business\Internal\Install\LocaleInstaller; use Spryker\Zed\Locale\Business\Manager\LocaleManager; +use Spryker\Zed\Locale\LocaleDependencyProvider; /** * @method \Spryker\Zed\Locale\LocaleConfig getConfig() @@ -48,4 +50,12 @@ public function createInstaller() return $installer; } + + /** + * @return \Spryker\Shared\Kernel\Store + */ + public function getStore(): Store + { + return $this->getProvidedDependency(LocaleDependencyProvider::STORE); + } } diff --git a/src/Spryker/Zed/Locale/Business/LocaleFacade.php b/src/Spryker/Zed/Locale/Business/LocaleFacade.php index 109cc6e..e01cd32 100644 --- a/src/Spryker/Zed/Locale/Business/LocaleFacade.php +++ b/src/Spryker/Zed/Locale/Business/LocaleFacade.php @@ -7,6 +7,7 @@ namespace Spryker\Zed\Locale\Business; +use Generated\Shared\Transfer\LocaleTransfer; use Spryker\Shared\Kernel\Store; use Spryker\Zed\Kernel\Business\AbstractFacade; @@ -199,4 +200,20 @@ public function getLocaleCollection() return $localeManager->getLocaleCollection(); } + + /** + * {@inheritdoc} + * + * @api + * + * @param \Generated\Shared\Transfer\LocaleTransfer $localeTransfer + * + * @return \Generated\Shared\Transfer\LocaleTransfer + */ + public function setCurrentLocale(LocaleTransfer $localeTransfer): LocaleTransfer + { + $this->getFactory()->getStore()->setCurrentLocale($localeTransfer->getLocaleName()); + + return $localeTransfer; + } } diff --git a/src/Spryker/Zed/Locale/Business/LocaleFacadeInterface.php b/src/Spryker/Zed/Locale/Business/LocaleFacadeInterface.php index 49751c3..0254f9c 100644 --- a/src/Spryker/Zed/Locale/Business/LocaleFacadeInterface.php +++ b/src/Spryker/Zed/Locale/Business/LocaleFacadeInterface.php @@ -7,6 +7,8 @@ namespace Spryker\Zed\Locale\Business; +use Generated\Shared\Transfer\LocaleTransfer; + interface LocaleFacadeInterface { /** @@ -146,4 +148,16 @@ public function install(); * @return \Generated\Shared\Transfer\LocaleTransfer[] */ public function getLocaleCollection(); + + /** + * Specification: + * - Sets current locale; + * + * @api + * + * @param \Generated\Shared\Transfer\LocaleTransfer $localeTransfer + * + * @return \Generated\Shared\Transfer\LocaleTransfer + */ + public function setCurrentLocale(LocaleTransfer $localeTransfer): LocaleTransfer; } diff --git a/src/Spryker/Zed/Locale/Communication/LocaleCommunicationFactory.php b/src/Spryker/Zed/Locale/Communication/LocaleCommunicationFactory.php index b2f9190..fa08aac 100644 --- a/src/Spryker/Zed/Locale/Communication/LocaleCommunicationFactory.php +++ b/src/Spryker/Zed/Locale/Communication/LocaleCommunicationFactory.php @@ -7,7 +7,9 @@ namespace Spryker\Zed\Locale\Communication; +use Spryker\Shared\LocaleExtension\Dependency\Plugin\LocalePluginInterface; use Spryker\Zed\Kernel\Communication\AbstractCommunicationFactory; +use Spryker\Zed\Locale\LocaleDependencyProvider; /** * @method \Spryker\Zed\Locale\LocaleConfig getConfig() @@ -16,4 +18,11 @@ */ class LocaleCommunicationFactory extends AbstractCommunicationFactory { + /** + * @return \Spryker\Shared\LocaleExtension\Dependency\Plugin\LocalePluginInterface + */ + public function getLocalePlugin(): LocalePluginInterface + { + return $this->getProvidedDependency(LocaleDependencyProvider::PLUGIN_LOCALE); + } } diff --git a/src/Spryker/Zed/Locale/Communication/Plugin/Application/LocaleApplicationPlugin.php b/src/Spryker/Zed/Locale/Communication/Plugin/Application/LocaleApplicationPlugin.php new file mode 100644 index 0000000..7003a8e --- /dev/null +++ b/src/Spryker/Zed/Locale/Communication/Plugin/Application/LocaleApplicationPlugin.php @@ -0,0 +1,52 @@ +set(static::BC_FEATURE_FLAG_LOCALE_LISTENER, false); + $container->set(static::SERVICE_LOCALE, function (ContainerInterface $container): string { + $localeTransfer = $this->getFactory()->getLocalePlugin()->getLocaleTransfer($container); + + $this->getFacade()->setCurrentLocale($localeTransfer); + + return $localeTransfer->getLocaleName(); + }); + + return $container; + } +} diff --git a/src/Spryker/Zed/Locale/Communication/Plugin/EventDispatcher/LocaleEventDispatcherPlugin.php b/src/Spryker/Zed/Locale/Communication/Plugin/EventDispatcher/LocaleEventDispatcherPlugin.php new file mode 100644 index 0000000..384a292 --- /dev/null +++ b/src/Spryker/Zed/Locale/Communication/Plugin/EventDispatcher/LocaleEventDispatcherPlugin.php @@ -0,0 +1,80 @@ +addListener( + KernelEvents::REQUEST, + function (GetResponseEvent $event) use ($container) { + $request = $event->getRequest(); + $request->setDefaultLocale($this->getLocale($container)); + + $this->setRequestLocale($request); + }, + static::EVENT_PRIORITY + ); + + return $eventDispatcher; + } + + /** + * @param \Symfony\Component\HttpFoundation\Request $request + * + * @return \Symfony\Component\HttpFoundation\Request + */ + protected function setRequestLocale(Request $request): Request + { + $locale = $request->attributes->get('_locale'); + if ($locale) { + $request->setLocale($locale); + } + + return $request; + } + + /** + * @param \Spryker\Service\Container\ContainerInterface $container + * + * @return string + */ + protected function getLocale(ContainerInterface $container): string + { + return $container->get(static::SERVICE_LOCALE); + } +} diff --git a/src/Spryker/Zed/Locale/Communication/Plugin/Locale/LocaleLocalePlugin.php b/src/Spryker/Zed/Locale/Communication/Plugin/Locale/LocaleLocalePlugin.php new file mode 100644 index 0000000..0959311 --- /dev/null +++ b/src/Spryker/Zed/Locale/Communication/Plugin/Locale/LocaleLocalePlugin.php @@ -0,0 +1,36 @@ +getFacade()->getCurrentLocale(); + } +} diff --git a/src/Spryker/Zed/Locale/LocaleDependencyProvider.php b/src/Spryker/Zed/Locale/LocaleDependencyProvider.php index 3a21dd4..3d3d4b0 100644 --- a/src/Spryker/Zed/Locale/LocaleDependencyProvider.php +++ b/src/Spryker/Zed/Locale/LocaleDependencyProvider.php @@ -7,11 +7,77 @@ namespace Spryker\Zed\Locale; +use Spryker\Shared\Kernel\Store; +use Spryker\Shared\LocaleExtension\Dependency\Plugin\LocalePluginInterface; use Spryker\Zed\Kernel\AbstractBundleDependencyProvider; +use Spryker\Zed\Kernel\Container; +use Spryker\Zed\Locale\Communication\Plugin\Locale\LocaleLocalePlugin; /** * @method \Spryker\Zed\Locale\LocaleConfig getConfig() */ class LocaleDependencyProvider extends AbstractBundleDependencyProvider { + public const PLUGIN_LOCALE = 'PLUGIN_LOCALE'; + public const STORE = 'STORE'; + + /** + * @param \Spryker\Zed\Kernel\Container $container + * + * @return \Spryker\Zed\Kernel\Container + */ + public function provideCommunicationLayerDependencies(Container $container): Container + { + $container = $this->addLocalePlugin($container); + + return $container; + } + + /** + * @param \Spryker\Zed\Kernel\Container $container + * + * @return \Spryker\Zed\Kernel\Container + */ + public function provideBusinessLayerDependencies(Container $container): Container + { + $container = $this->addStore($container); + + return $container; + } + + /** + * @param \Spryker\Zed\Kernel\Container $container + * + * @return \Spryker\Zed\Kernel\Container + */ + protected function addLocalePlugin(Container $container): Container + { + $container->set(static::PLUGIN_LOCALE, function (): LocalePluginInterface { + return $this->getLocalePlugin(); + }); + + return $container; + } + + /** + * @return \Spryker\Shared\LocaleExtension\Dependency\Plugin\LocalePluginInterface + */ + protected function getLocalePlugin(): LocalePluginInterface + { + return new LocaleLocalePlugin(); + } + + /** + * @param \Spryker\Zed\Kernel\Container $container + * + * @return \Spryker\Zed\Kernel\Container + */ + protected function addStore(Container $container): Container + { + $container->set(static::STORE, function () { + return Store::getInstance(); + }); + + return $container; + } } diff --git a/tests/SprykerTest/Zed/Locale/Business/LocaleFacadeTest.php b/tests/SprykerTest/Zed/Locale/Business/LocaleFacadeTest.php index feedb96..4d5d990 100644 --- a/tests/SprykerTest/Zed/Locale/Business/LocaleFacadeTest.php +++ b/tests/SprykerTest/Zed/Locale/Business/LocaleFacadeTest.php @@ -8,6 +8,7 @@ namespace SprykerTest\Zed\Locale\Business; use Codeception\Test\Unit; +use Generated\Shared\Transfer\LocaleTransfer; use Spryker\Shared\Kernel\Store; use Spryker\Zed\Locale\Business\LocaleFacade; use Spryker\Zed\Locale\Persistence\LocaleQueryContainer; @@ -86,4 +87,21 @@ public function testAvailableLocalesHasDifferentIdsThanConfiguredOnes() array_keys($this->localeNames) ); } + + /** + * @return void + */ + public function testCurrentLocaleIsChangeable(): void + { + //Arrange + $currentLocale = $this->localeFacade->getCurrentLocale(); + $newLocale = (new LocaleTransfer())->setLocaleName('de_DE'); + + //Act + $this->localeFacade->setCurrentLocale($newLocale); + $newCurentLocale = $this->localeFacade->getCurrentLocale(); + + //Assert + $this->assertSame($currentLocale->getLocaleName(), $newCurentLocale->getLocaleName()); + } }