diff --git a/UPGRADE.md b/UPGRADE.md index 8f3498fe5..72ba6eb50 100644 --- a/UPGRADE.md +++ b/UPGRADE.md @@ -27,9 +27,10 @@ | Old Route | New route | |:--------------------------------------|:---------------------------------------| - | `{channelCode}/address-book/*` | `address-book/*` | + | `{channelCode}/address-book/*` | `address-book/*` | | `{channelCode}/checkout/*` | `checkout/*` | - | `{channelCode}/orders/*` | `orders/*` | + | `{channelCode}/orders/*` | `orders/*` | + | `{channelCode}/taxons/*` | `taxons/*` | # UPGRADE FROM 1.0.0-beta.17 to 1.0.0-beta.18 diff --git a/doc/swagger.yml b/doc/swagger.yml index bb1a6590a..456a47e5d 100644 --- a/doc/swagger.yml +++ b/doc/swagger.yml @@ -636,9 +636,8 @@ paths: description: "A paginated list of all reviews related to the product identified by slug." schema: $ref: "#/definitions/ProductReviewsPage" - /{channelCode}/taxons: - parameters: - - $ref: "#/parameters/ChannelCode" + + /taxons: get: tags: - "taxons" @@ -658,9 +657,8 @@ paths: type: "array" items: $ref: "#/definitions/Taxon" - /{channelCode}/taxons/{code}: - parameters: - - $ref: "#/parameters/ChannelCode" + + /taxons/{code}: get: tags: - "taxons" diff --git a/spec/Http/RequestBasedLocaleProviderSpec.php b/spec/Http/RequestBasedLocaleProviderSpec.php index a2b725161..f12d8066d 100644 --- a/spec/Http/RequestBasedLocaleProviderSpec.php +++ b/spec/Http/RequestBasedLocaleProviderSpec.php @@ -5,9 +5,8 @@ namespace spec\Sylius\ShopApiPlugin\Http; use PhpSpec\ObjectBehavior; -use Sylius\Component\Channel\Repository\ChannelRepositoryInterface; +use Sylius\Component\Channel\Context\RequestBased\RequestResolverInterface; use Sylius\Component\Core\Model\ChannelInterface; -use Sylius\ShopApiPlugin\Checker\ChannelExistenceCheckerInterface; use Sylius\ShopApiPlugin\Exception\ChannelNotFoundException; use Sylius\ShopApiPlugin\Http\RequestBasedLocaleProviderInterface; use Sylius\ShopApiPlugin\Provider\SupportedLocaleProviderInterface; @@ -17,11 +16,10 @@ final class RequestBasedLocaleProviderSpec extends ObjectBehavior { function let( - ChannelRepositoryInterface $channelRepository, - ChannelExistenceCheckerInterface $channelExistenceChecker, + RequestResolverInterface $hostnameBasedRequestResolver, SupportedLocaleProviderInterface $supportedLocaleProvider ): void { - $this->beConstructedWith($channelRepository, $channelExistenceChecker, $supportedLocaleProvider); + $this->beConstructedWith($hostnameBasedRequestResolver, $supportedLocaleProvider); } function it_implements_request_based_locale_provider_interface(): void @@ -29,59 +27,39 @@ function it_implements_request_based_locale_provider_interface(): void $this->shouldImplement(RequestBasedLocaleProviderInterface::class); } - function it_uses_channel_code_and_locale_provider_to_return_request_locale( - ChannelRepositoryInterface $channelRepository, - ChannelExistenceCheckerInterface $channelExistenceChecker, + function it_provides_a_locale_code( + RequestResolverInterface $hostnameBasedRequestResolver, SupportedLocaleProviderInterface $supportedLocaleProvider, ChannelInterface $channel, Request $request ): void { - $request->attributes = new ParameterBag(['channelCode' => 'WEB_US']); $request->query = new ParameterBag(['locale' => 'fr_FR']); - $channelExistenceChecker->withCode('WEB_US')->shouldBeCalled(); - $channelRepository->findOneByCode('WEB_US')->willReturn($channel); - + $hostnameBasedRequestResolver->findChannel($request)->willReturn($channel); $supportedLocaleProvider->provide('fr_FR', $channel)->willReturn('fr_FR'); $this->getLocaleCode($request)->shouldReturn('fr_FR'); } - function it_provides_locale_code_even_if_it_is_not_defined_explicitly( - ChannelRepositoryInterface $channelRepository, - ChannelExistenceCheckerInterface $channelExistenceChecker, + function it_provides_a_locale_code_even_if_it_is_not_defined_explicitly( + RequestResolverInterface $hostnameBasedRequestResolver, SupportedLocaleProviderInterface $supportedLocaleProvider, ChannelInterface $channel, Request $request ): void { - $request->attributes = new ParameterBag(['channelCode' => 'WEB_US']); $request->query = new ParameterBag([]); - $channelExistenceChecker->withCode('WEB_US')->shouldBeCalled(); - $channelRepository->findOneByCode('WEB_US')->willReturn($channel); - + $hostnameBasedRequestResolver->findChannel($request)->willReturn($channel); $supportedLocaleProvider->provide(null, $channel)->willReturn('en_US'); $this->getLocaleCode($request)->shouldReturn('en_US'); } - function it_throws_exception_if_channel_code_is_not_defined(Request $request): void - { - $request->attributes = new ParameterBag([]); - - $this - ->shouldThrow(\InvalidArgumentException::class) - ->during('getLocaleCode', [$request]) - ; - } - - function it_throws_exception_if_channel_with_given_code_does_not_exist( - Request $request, - ChannelExistenceCheckerInterface $channelExistenceChecker + function it_throws_an_exception_if_channel_cannot_be_resolved( + RequestResolverInterface $hostnameBasedRequestResolver, + Request $request ): void { - $request->attributes = new ParameterBag(['channelCode' => 'WEB_PL']); - - $channelExistenceChecker->withCode('WEB_PL')->willThrow(ChannelNotFoundException::class); + $hostnameBasedRequestResolver->findChannel($request)->willReturn(null); $this ->shouldThrow(ChannelNotFoundException::class) diff --git a/src/Controller/Taxon/ShowTaxonDetailsAction.php b/src/Controller/Taxon/ShowTaxonDetailsAction.php index 33da77e10..d87857b62 100644 --- a/src/Controller/Taxon/ShowTaxonDetailsAction.php +++ b/src/Controller/Taxon/ShowTaxonDetailsAction.php @@ -6,6 +6,7 @@ use FOS\RestBundle\View\View; use FOS\RestBundle\View\ViewHandlerInterface; +use Sylius\Component\Core\Model\TaxonInterface; use Sylius\Component\Taxonomy\Repository\TaxonRepositoryInterface; use Sylius\ShopApiPlugin\Factory\Taxon\TaxonDetailsViewFactoryInterface; use Sylius\ShopApiPlugin\Http\RequestBasedLocaleProviderInterface; @@ -42,14 +43,14 @@ public function __construct( public function __invoke(Request $request): Response { $code = $request->attributes->get('code'); - $locale = $this->requestBasedLocaleProvider->getLocaleCode($request); - + /** @var TaxonInterface|null $taxon */ $taxon = $this->taxonRepository->findOneBy(['code' => $code]); - if (null === $taxon) { throw new NotFoundHttpException(sprintf('Taxon with code %s has not been found.', $code)); } - return $this->viewHandler->handle(View::create($this->taxonViewFactory->create($taxon, $locale), Response::HTTP_OK)); + $localeCode = $this->requestBasedLocaleProvider->getLocaleCode($request); + + return $this->viewHandler->handle(View::create($this->taxonViewFactory->create($taxon, $localeCode), Response::HTTP_OK)); } } diff --git a/src/Controller/Taxon/ShowTaxonTreeAction.php b/src/Controller/Taxon/ShowTaxonTreeAction.php index 84c4bcb00..9b671aab8 100644 --- a/src/Controller/Taxon/ShowTaxonTreeAction.php +++ b/src/Controller/Taxon/ShowTaxonTreeAction.php @@ -42,25 +42,25 @@ public function __construct( public function __invoke(Request $request): Response { - $locale = $this->requestBasedLocaleProvider->getLocaleCode($request); + $localeCode = $this->requestBasedLocaleProvider->getLocaleCode($request); $taxons = $this->taxonRepository->findRootNodes(); $taxonViews = []; /** @var TaxonInterface $taxon */ foreach ($taxons as $taxon) { - $taxonViews[] = $this->buildTaxonView($taxon, $locale); + $taxonViews[] = $this->buildTaxonView($taxon, $localeCode); } return $this->viewHandler->handle(View::create($taxonViews, Response::HTTP_OK)); } - private function buildTaxonView(TaxonInterface $taxon, $locale): TaxonView + private function buildTaxonView(TaxonInterface $taxon, string $localeCode): TaxonView { - $taxonView = $this->taxonViewFactory->create($taxon, $locale); + $taxonView = $this->taxonViewFactory->create($taxon, $localeCode); foreach ($taxon->getChildren() as $childTaxon) { - $taxonView->children[] = $this->buildTaxonView($childTaxon, $locale); + $taxonView->children[] = $this->buildTaxonView($childTaxon, $localeCode); } return $taxonView; diff --git a/src/Exception/ChannelNotFoundException.php b/src/Exception/ChannelNotFoundException.php index dd65560a3..e25d1d8e6 100644 --- a/src/Exception/ChannelNotFoundException.php +++ b/src/Exception/ChannelNotFoundException.php @@ -6,6 +6,11 @@ final class ChannelNotFoundException extends \InvalidArgumentException { + public static function occur(): self + { + return new self('Channel has not been found.'); + } + public static function withCode(string $channelCode): self { return new self(sprintf('Channel with code %s has not been found.', $channelCode)); diff --git a/src/Http/RequestBasedLocaleProvider.php b/src/Http/RequestBasedLocaleProvider.php index b211ddd2f..b8df20a4d 100644 --- a/src/Http/RequestBasedLocaleProvider.php +++ b/src/Http/RequestBasedLocaleProvider.php @@ -4,45 +4,36 @@ namespace Sylius\ShopApiPlugin\Http; -use Sylius\Component\Channel\Repository\ChannelRepositoryInterface; +use Sylius\Component\Channel\Context\RequestBased\RequestResolverInterface; use Sylius\Component\Core\Model\ChannelInterface; -use Sylius\ShopApiPlugin\Checker\ChannelExistenceCheckerInterface; use Sylius\ShopApiPlugin\Exception\ChannelNotFoundException; use Sylius\ShopApiPlugin\Provider\SupportedLocaleProviderInterface; use Symfony\Component\HttpFoundation\Request; -use Webmozart\Assert\Assert; final class RequestBasedLocaleProvider implements RequestBasedLocaleProviderInterface { - /** @var ChannelRepositoryInterface */ - private $channelRepository; - - /** @var ChannelExistenceCheckerInterface */ - private $channelExistenceChecker; + /** @var RequestResolverInterface */ + private $hostnameBasedRequestResolver; /** @var SupportedLocaleProviderInterface */ private $supportedLocaleProvider; public function __construct( - ChannelRepositoryInterface $channelRepository, - ChannelExistenceCheckerInterface $channelExistenceChecker, + RequestResolverInterface $hostnameBasedRequestResolver, SupportedLocaleProviderInterface $supportedLocaleProvider ) { - $this->channelRepository = $channelRepository; - $this->channelExistenceChecker = $channelExistenceChecker; + $this->hostnameBasedRequestResolver = $hostnameBasedRequestResolver; $this->supportedLocaleProvider = $supportedLocaleProvider; } - /** @throws ChannelNotFoundException|\InvalidArgumentException */ + /** @throws ChannelNotFoundException */ public function getLocaleCode(Request $request): string { - Assert::true($request->attributes->has('channelCode')); - - $channelCode = $request->attributes->get('channelCode'); - $this->channelExistenceChecker->withCode($channelCode); - - /** @var ChannelInterface $channel */ - $channel = $this->channelRepository->findOneByCode($channelCode); + /** @var ChannelInterface|null $channel */ + $channel = $this->hostnameBasedRequestResolver->findChannel($request); + if (null === $channel) { + throw ChannelNotFoundException::occur(); + } return $this->supportedLocaleProvider->provide($request->query->get('locale'), $channel); } diff --git a/src/Resources/config/routing.yml b/src/Resources/config/routing.yml index 215eb8bf9..b2f2d660e 100644 --- a/src/Resources/config/routing.yml +++ b/src/Resources/config/routing.yml @@ -12,7 +12,7 @@ sylius_shop_api_product_by_code: sylius_shop_api_taxon: resource: "@ShopApiPlugin/Resources/config/routing/taxon.yml" - prefix: /shop-api/{channelCode} + prefix: /shop-api sylius_shop_api_register: resource: "@ShopApiPlugin/Resources/config/routing/register.yml" diff --git a/src/Resources/config/services/http.xml b/src/Resources/config/services/http.xml index 28fc90561..fcd83999c 100644 --- a/src/Resources/config/services/http.xml +++ b/src/Resources/config/services/http.xml @@ -10,8 +10,7 @@ - - + diff --git a/tests/Controller/Taxon/TaxonShowDetailsApiTest.php b/tests/Controller/Taxon/TaxonShowDetailsApiTest.php index ef681d81b..cae30a755 100644 --- a/tests/Controller/Taxon/TaxonShowDetailsApiTest.php +++ b/tests/Controller/Taxon/TaxonShowDetailsApiTest.php @@ -16,7 +16,7 @@ public function it_shows_summary_of_a_chosen_taxon_with_fallback_locale_from_cha { $this->loadFixturesFromFiles(['shop.yml']); - $this->client->request('GET', '/shop-api/WEB_GB/taxons/T_SHIRTS', [], [], self::CONTENT_TYPE_HEADER); + $this->client->request('GET', '/shop-api/taxons/T_SHIRTS', [], [], self::CONTENT_TYPE_HEADER); $response = $this->client->getResponse(); $this->assertResponse($response, 'taxon/one_of_taxons_response', Response::HTTP_OK); @@ -29,7 +29,7 @@ public function it_shows_summary_of_a_chosen_taxon_with_strange_code(): void { $this->loadFixturesFromFiles(['shop.yml']); - $this->client->request('GET', '/shop-api/WEB_GB/taxons/de%3Flol%3Dxd%23boom?locale=en_GB', [], [], self::CONTENT_TYPE_HEADER); + $this->client->request('GET', '/shop-api/taxons/de%3Flol%3Dxd%23boom?locale=en_GB', [], [], self::CONTENT_TYPE_HEADER); $response = $this->client->getResponse(); $this->assertResponse($response, 'taxon/strange_taxon_code_response', Response::HTTP_OK); @@ -42,22 +42,9 @@ public function it_shows_summary_of_a_chosen_taxon_in_different_language(): void { $this->loadFixturesFromFiles(['shop.yml']); - $this->client->request('GET', '/shop-api/WEB_GB/taxons/T_SHIRTS?locale=de_DE', [], [], self::CONTENT_TYPE_HEADER); + $this->client->request('GET', '/shop-api/taxons/T_SHIRTS?locale=de_DE', [], [], self::CONTENT_TYPE_HEADER); $response = $this->client->getResponse(); $this->assertResponse($response, 'taxon/german_one_of_taxons_response', Response::HTTP_OK); } - - /** - * @test - */ - public function it_does_not_show_taxon_details_in_non_existent_channel(): void - { - $this->loadFixturesFromFiles(['shop.yml']); - - $this->client->request('GET', '/shop-api/SPACE_KLINGON/taxons/T_SHIRTS?locale=en_GB', [], [], self::CONTENT_TYPE_HEADER); - $response = $this->client->getResponse(); - - $this->assertResponse($response, 'channel_has_not_been_found_response', Response::HTTP_NOT_FOUND); - } } diff --git a/tests/Controller/Taxon/TaxonShowTreeApiTest.php b/tests/Controller/Taxon/TaxonShowTreeApiTest.php index 9a2f10992..840c9c3f7 100644 --- a/tests/Controller/Taxon/TaxonShowTreeApiTest.php +++ b/tests/Controller/Taxon/TaxonShowTreeApiTest.php @@ -16,7 +16,7 @@ public function it_shows_tree_of_all_taxons_with_fallback_locale_from_channel(): { $this->loadFixturesFromFiles(['shop.yml']); - $this->client->request('GET', '/shop-api/WEB_GB/taxons/', [], [], self::CONTENT_TYPE_HEADER); + $this->client->request('GET', '/shop-api/taxons/', [], [], self::CONTENT_TYPE_HEADER); $response = $this->client->getResponse(); @@ -30,24 +30,10 @@ public function it_shows_tree_of_all_taxons_in_different_language(): void { $this->loadFixturesFromFiles(['shop.yml']); - $this->client->request('GET', '/shop-api/WEB_GB/taxons/?locale=de_DE', [], [], self::CONTENT_TYPE_HEADER); + $this->client->request('GET', '/shop-api/taxons/?locale=de_DE', [], [], self::CONTENT_TYPE_HEADER); $response = $this->client->getResponse(); $this->assertResponse($response, 'taxon/german_all_taxons_response', Response::HTTP_OK); } - - /** - * @test - */ - public function it_does_not_show_taxons_tree_in_non_existent_channel(): void - { - $this->loadFixturesFromFiles(['shop.yml']); - - $this->client->request('GET', '/shop-api/SPACE_KLINGON/taxons/', [], [], self::CONTENT_TYPE_HEADER); - - $response = $this->client->getResponse(); - - $this->assertResponse($response, 'channel_has_not_been_found_response', Response::HTTP_NOT_FOUND); - } }