mirror of
https://github.com/Sylius/Sylius.git
synced 2026-07-14 17:10:53 +00:00
[Locales] Create ADR for locales exposing
This commit is contained in:
parent
d516bf1233
commit
90ceff637e
5 changed files with 55 additions and 17 deletions
|
|
@ -0,0 +1,26 @@
|
||||||
|
# Using data provider for getting available locales in active channel for shop user
|
||||||
|
|
||||||
|
* Status: proposed
|
||||||
|
* Date: 2021-07-05
|
||||||
|
|
||||||
|
## Context and Problem Statement
|
||||||
|
Customer should have access only to locales available in their channel
|
||||||
|
|
||||||
|
## Considered Options
|
||||||
|
|
||||||
|
### Using Doctrine Collection extension
|
||||||
|
|
||||||
|
* Good, because consistent with actual approach to modifying responses content
|
||||||
|
* Good, because works with rest of API extension like pagination
|
||||||
|
* Bad, because locales don't have relation to channel, so using Doctrine Collection extension is extremely hard.
|
||||||
|
|
||||||
|
### Using Data Provider
|
||||||
|
|
||||||
|
* Good, because we already have this approach for older resources
|
||||||
|
* Good, because easy to implement
|
||||||
|
* Bad, because using data providers omits extra Doctrine extensions like pagination
|
||||||
|
|
||||||
|
## Decision Outcome
|
||||||
|
|
||||||
|
Chosen option: Using Data Provider
|
||||||
|
Shops shouldn't have many locales for each channel, so lack of a pagination is smaller problem than creating overcomplicated query in Doctrine Collection extension
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
@locales
|
@locales
|
||||||
Feature: Getting a available locales in current channel
|
Feature: Getting available locales in the current channel
|
||||||
In order to use a shop in chosen locale
|
In order to use a shop in chosen locale
|
||||||
As a Customer
|
As a Customer
|
||||||
I want to be able to get available locales
|
I want to be able to get available locales
|
||||||
|
|
|
||||||
|
|
@ -56,9 +56,11 @@ final class LocaleContext implements Context
|
||||||
*/
|
*/
|
||||||
public function theLocaleWithCodeShouldBeAvailable(string $name, string $code): void
|
public function theLocaleWithCodeShouldBeAvailable(string $name, string $code): void
|
||||||
{
|
{
|
||||||
Assert::true(
|
Assert::true($this->isLocaleWithNameAndCode(
|
||||||
$this->isLocaleWithName($name, $this->responseChecker->getCollection($this->client->getLastResponse()))
|
$this->responseChecker->getCollection($this->client->getLastResponse()),
|
||||||
);
|
$name,
|
||||||
|
$code
|
||||||
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -66,15 +68,17 @@ final class LocaleContext implements Context
|
||||||
*/
|
*/
|
||||||
public function theLocaleWithCodeShouldNotBeAvailable(string $name, string $code): void
|
public function theLocaleWithCodeShouldNotBeAvailable(string $name, string $code): void
|
||||||
{
|
{
|
||||||
Assert::false(
|
Assert::false($this->isLocaleWithNameAndCode(
|
||||||
$this->isLocaleWithName($name, $this->responseChecker->getCollection($this->client->getLastResponse()))
|
$this->responseChecker->getCollection($this->client->getLastResponse()),
|
||||||
);
|
$name,
|
||||||
|
$code
|
||||||
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
private function isLocaleWithName(string $name, array $locales): bool
|
private function isLocaleWithNameAndCode(array $locales, string $name, string $code): bool
|
||||||
{
|
{
|
||||||
foreach ($locales as $locale) {
|
foreach ($locales as $locale) {
|
||||||
if ($locale['name'] === $name) {
|
if ($locale['name'] === $name && $locale['code'] === $code) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -15,8 +15,10 @@ namespace Sylius\Bundle\ApiBundle\DataProvider;
|
||||||
|
|
||||||
use ApiPlatform\Core\DataProvider\CollectionDataProviderInterface;
|
use ApiPlatform\Core\DataProvider\CollectionDataProviderInterface;
|
||||||
use ApiPlatform\Core\DataProvider\RestrictedDataProviderInterface;
|
use ApiPlatform\Core\DataProvider\RestrictedDataProviderInterface;
|
||||||
|
use Doctrine\Common\Collections\Collection;
|
||||||
use Sylius\Bundle\ApiBundle\Context\UserContextInterface;
|
use Sylius\Bundle\ApiBundle\Context\UserContextInterface;
|
||||||
use Sylius\Bundle\ApiBundle\Serializer\ContextKeys;
|
use Sylius\Bundle\ApiBundle\Serializer\ContextKeys;
|
||||||
|
use Sylius\Component\Core\Model\AdminUserInterface;
|
||||||
use Sylius\Component\Core\Model\ChannelInterface;
|
use Sylius\Component\Core\Model\ChannelInterface;
|
||||||
use Sylius\Component\Locale\Model\LocaleInterface;
|
use Sylius\Component\Locale\Model\LocaleInterface;
|
||||||
use Sylius\Component\Resource\Repository\RepositoryInterface;
|
use Sylius\Component\Resource\Repository\RepositoryInterface;
|
||||||
|
|
@ -31,8 +33,10 @@ final class LocaleCollectionDataProvider implements CollectionDataProviderInterf
|
||||||
/** @var UserContextInterface */
|
/** @var UserContextInterface */
|
||||||
private $userContext;
|
private $userContext;
|
||||||
|
|
||||||
public function __construct(RepositoryInterface $localeRepository, UserContextInterface $userContext)
|
public function __construct(
|
||||||
{
|
RepositoryInterface $localeRepository,
|
||||||
|
UserContextInterface $userContext
|
||||||
|
) {
|
||||||
$this->localeRepository = $localeRepository;
|
$this->localeRepository = $localeRepository;
|
||||||
$this->userContext = $userContext;
|
$this->userContext = $userContext;
|
||||||
}
|
}
|
||||||
|
|
@ -44,12 +48,14 @@ final class LocaleCollectionDataProvider implements CollectionDataProviderInterf
|
||||||
|
|
||||||
public function getCollection(string $resourceClass, string $operationName = null, array $context = [])
|
public function getCollection(string $resourceClass, string $operationName = null, array $context = [])
|
||||||
{
|
{
|
||||||
Assert::keyExists($context, ContextKeys::CHANNEL);
|
|
||||||
|
|
||||||
$user = $this->userContext->getUser();
|
$user = $this->userContext->getUser();
|
||||||
if ($user !== null && in_array('ROLE_API_ACCESS', $user->getRoles())) {
|
|
||||||
|
if ($user instanceof AdminUserInterface && in_array('ROLE_API_ACCESS', $user->getRoles())) {
|
||||||
return $this->localeRepository->findAll();
|
return $this->localeRepository->findAll();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Assert::keyExists($context, ContextKeys::CHANNEL);
|
||||||
|
|
||||||
/** @var ChannelInterface $channel */
|
/** @var ChannelInterface $channel */
|
||||||
$channel = $context[ContextKeys::CHANNEL];
|
$channel = $context[ContextKeys::CHANNEL];
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -14,9 +14,11 @@ declare(strict_types=1);
|
||||||
namespace spec\Sylius\Bundle\ApiBundle\DataProvider;
|
namespace spec\Sylius\Bundle\ApiBundle\DataProvider;
|
||||||
|
|
||||||
use Doctrine\Common\Collections\ArrayCollection;
|
use Doctrine\Common\Collections\ArrayCollection;
|
||||||
|
use Doctrine\Common\Collections\Collection;
|
||||||
use PhpSpec\ObjectBehavior;
|
use PhpSpec\ObjectBehavior;
|
||||||
use Sylius\Bundle\ApiBundle\Context\UserContextInterface;
|
use Sylius\Bundle\ApiBundle\Context\UserContextInterface;
|
||||||
use Sylius\Bundle\ApiBundle\Serializer\ContextKeys;
|
use Sylius\Bundle\ApiBundle\Serializer\ContextKeys;
|
||||||
|
use Sylius\Component\Core\Model\AdminUserInterface;
|
||||||
use Sylius\Component\Core\Model\ChannelInterface;
|
use Sylius\Component\Core\Model\ChannelInterface;
|
||||||
use Sylius\Component\Core\Model\ProductInterface;
|
use Sylius\Component\Core\Model\ProductInterface;
|
||||||
use Sylius\Component\Locale\Model\LocaleInterface;
|
use Sylius\Component\Locale\Model\LocaleInterface;
|
||||||
|
|
@ -57,17 +59,17 @@ final class LocaleCollectionDataProviderSpec extends ObjectBehavior
|
||||||
$channel->addLocale($firstLocale);
|
$channel->addLocale($firstLocale);
|
||||||
$channel->addLocale($secondLocale);
|
$channel->addLocale($secondLocale);
|
||||||
|
|
||||||
$channel->getLocales()->willReturn([$firstLocale, $secondLocale]);
|
$channel->getLocales()->willReturn(new ArrayCollection([$firstLocale->getWrappedObject(), $secondLocale->getWrappedObject()]));
|
||||||
|
|
||||||
$this
|
$this
|
||||||
->getCollection(LocaleInterface::class, 'get', [ContextKeys::CHANNEL => $channel])
|
->getCollection(LocaleInterface::class, 'get', [ContextKeys::CHANNEL => $channel])
|
||||||
->shouldReturn(new ArrayCollection([$firstLocale, $secondLocale]))
|
->shouldBeLike(new ArrayCollection([$firstLocale->getWrappedObject(), $secondLocale->getWrappedObject()]))
|
||||||
;
|
;
|
||||||
}
|
}
|
||||||
|
|
||||||
function it_provides_all_locales_if_user_is_admin(
|
function it_provides_all_locales_if_user_is_admin(
|
||||||
UserContextInterface $userContext,
|
UserContextInterface $userContext,
|
||||||
UserInterface $user,
|
AdminUserInterface $user,
|
||||||
ChannelInterface $channel,
|
ChannelInterface $channel,
|
||||||
LocaleInterface $firstLocale,
|
LocaleInterface $firstLocale,
|
||||||
LocaleInterface $secondLocale,
|
LocaleInterface $secondLocale,
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue