From d6d087295353de695cd8f6bc77a0b53c1a60277d Mon Sep 17 00:00:00 2001 From: Yaroslav Rogoza Date: Sat, 30 Jun 2018 16:40:31 +0300 Subject: [PATCH 01/10] Added URL rewrites data to the product interface --- .../Magento/CatalogGraphQl/etc/module.xml | 1 + .../CatalogGraphQl/etc/schema.graphqls | 1 + .../Model/Resolver/EntityUrl.php | 161 ++++++++++++++++++ .../Model/Resolver/UrlRewrite.php | 146 +++++----------- .../UrlRewriteGraphQl/etc/schema.graphqls | 12 +- 5 files changed, 219 insertions(+), 102 deletions(-) create mode 100644 app/code/Magento/UrlRewriteGraphQl/Model/Resolver/EntityUrl.php diff --git a/app/code/Magento/CatalogGraphQl/etc/module.xml b/app/code/Magento/CatalogGraphQl/etc/module.xml index 87696c129a714..2551664cc5f62 100644 --- a/app/code/Magento/CatalogGraphQl/etc/module.xml +++ b/app/code/Magento/CatalogGraphQl/etc/module.xml @@ -15,6 +15,7 @@ + diff --git a/app/code/Magento/CatalogGraphQl/etc/schema.graphqls b/app/code/Magento/CatalogGraphQl/etc/schema.graphqls index 762861de94e67..b7a5f7ac1c640 100644 --- a/app/code/Magento/CatalogGraphQl/etc/schema.graphqls +++ b/app/code/Magento/CatalogGraphQl/etc/schema.graphqls @@ -280,6 +280,7 @@ interface ProductInterface @typeResolver(class: "Magento\\CatalogGraphQl\\Model\ manufacturer: Int @doc(description: "A number representing the product's manufacturer") categories: [CategoryInterface] @doc(description: "The categories assigned to a product") @resolver(class: "Magento\\CatalogGraphQl\\Model\\Resolver\\Categories") canonical_url: String @doc(description: "Canonical URL") @resolver(class: "Magento\\CatalogGraphQl\\Model\\Resolver\\Product\\CanonicalUrl") + url_rewrites: [UrlRewrite] @doc(description: "URL rewrites list") @resolver(class: "Magento\\UrlRewriteGraphQl\\Model\\Resolver\\UrlRewrite") } interface PhysicalProductInterface @typeResolver(class: "Magento\\CatalogGraphQl\\Model\\ProductInterfaceTypeResolverComposite") @doc(description: "PhysicalProductInterface contains attributes specific to tangible products") { diff --git a/app/code/Magento/UrlRewriteGraphQl/Model/Resolver/EntityUrl.php b/app/code/Magento/UrlRewriteGraphQl/Model/Resolver/EntityUrl.php new file mode 100644 index 0000000000000..9790339dd10c6 --- /dev/null +++ b/app/code/Magento/UrlRewriteGraphQl/Model/Resolver/EntityUrl.php @@ -0,0 +1,161 @@ +urlFinder = $urlFinder; + $this->storeManager = $storeManager; + $this->valueFactory = $valueFactory; + $this->customUrlLocator = $customUrlLocator; + } + + /** + * {@inheritdoc} + */ + public function resolve( + Field $field, + $context, + ResolveInfo $info, + array $value = null, + array $args = null + ) : Value { + $result = function () { + return null; + }; + + if (isset($args['url'])) { + $url = $args['url']; + if (substr($url, 0, 1) === '/' && $url !== '/') { + $url = ltrim($url, '/'); + } + $customUrl = $this->customUrlLocator->locateUrl($url); + $url = $customUrl ?: $url; + $urlRewrite = $this->findCanonicalUrl($url); + if ($urlRewrite) { + $urlRewriteReturnArray = [ + 'id' => $urlRewrite->getEntityId(), + 'canonical_url' => $urlRewrite->getTargetPath(), + 'type' => $this->sanitizeType($urlRewrite->getEntityType()) + ]; + $result = function () use ($urlRewriteReturnArray) { + return $urlRewriteReturnArray; + }; + } + } + return $this->valueFactory->create($result); + } + + /** + * Find the canonical url passing through all redirects if any + * + * @param string $requestPath + * @return \Magento\UrlRewrite\Service\V1\Data\UrlRewrite|null + */ + private function findCanonicalUrl(string $requestPath) : ?\Magento\UrlRewrite\Service\V1\Data\UrlRewrite + { + $urlRewrite = $this->findUrlFromRequestPath($requestPath); + if ($urlRewrite && $urlRewrite->getRedirectType() > 0) { + while ($urlRewrite && $urlRewrite->getRedirectType() > 0) { + $urlRewrite = $this->findUrlFromRequestPath($urlRewrite->getTargetPath()); + } + } + if (!$urlRewrite) { + $urlRewrite = $this->findUrlFromTargetPath($requestPath); + } + + return $urlRewrite; + } + + /** + * Find a url from a request url on the current store + * + * @param string $requestPath + * @return \Magento\UrlRewrite\Service\V1\Data\UrlRewrite|null + */ + private function findUrlFromRequestPath(string $requestPath) : ?\Magento\UrlRewrite\Service\V1\Data\UrlRewrite + { + return $this->urlFinder->findOneByData( + [ + 'request_path' => $requestPath, + 'store_id' => $this->storeManager->getStore()->getId() + ] + ); + } + + /** + * Find a url from a target url on the current store + * + * @param string $targetPath + * @return \Magento\UrlRewrite\Service\V1\Data\UrlRewrite|null + */ + private function findUrlFromTargetPath(string $targetPath) : ?\Magento\UrlRewrite\Service\V1\Data\UrlRewrite + { + return $this->urlFinder->findOneByData( + [ + 'target_path' => $targetPath, + 'store_id' => $this->storeManager->getStore()->getId() + ] + ); + } + + /** + * Sanitize the type to fit schema specifications + * + * @param string $type + * @return string + */ + private function sanitizeType(string $type) : string + { + return strtoupper(str_replace('-', '_', $type)); + } +} diff --git a/app/code/Magento/UrlRewriteGraphQl/Model/Resolver/UrlRewrite.php b/app/code/Magento/UrlRewriteGraphQl/Model/Resolver/UrlRewrite.php index 3f07edc601909..e64912d171a63 100644 --- a/app/code/Magento/UrlRewriteGraphQl/Model/Resolver/UrlRewrite.php +++ b/app/code/Magento/UrlRewriteGraphQl/Model/Resolver/UrlRewrite.php @@ -12,51 +12,31 @@ use Magento\Framework\GraphQl\Query\Resolver\Value; use Magento\Framework\GraphQl\Query\Resolver\ValueFactory; use Magento\Framework\GraphQl\Query\ResolverInterface; -use Magento\Store\Model\StoreManagerInterface; +use Magento\Framework\Model\AbstractModel; use Magento\UrlRewrite\Model\UrlFinderInterface; -use Magento\UrlRewriteGraphQl\Model\Resolver\UrlRewrite\CustomUrlLocatorInterface; +use Magento\UrlRewrite\Service\V1\Data\UrlRewrite as UrlRewriteDTO; /** * UrlRewrite field resolver, used for GraphQL request processing. */ class UrlRewrite implements ResolverInterface { - /** - * @var UrlFinderInterface - */ private $urlFinder; - - /** - * @var StoreManagerInterface - */ - private $storeManager; - /** * @var ValueFactory */ private $valueFactory; - - /** - * @var CustomUrlLocatorInterface - */ - private $customUrlLocator; /** - * @param UrlFinderInterface $urlFinder - * @param StoreManagerInterface $storeManager * @param ValueFactory $valueFactory - * @param CustomUrlLocatorInterface $customUrlLocator + * @param UrlFinderInterface $urlFinder */ public function __construct( - UrlFinderInterface $urlFinder, - StoreManagerInterface $storeManager, ValueFactory $valueFactory, - CustomUrlLocatorInterface $customUrlLocator + UrlFinderInterface $urlFinder ) { - $this->urlFinder = $urlFinder; - $this->storeManager = $storeManager; $this->valueFactory = $valueFactory; - $this->customUrlLocator = $customUrlLocator; + $this->urlFinder = $urlFinder; } /** @@ -68,94 +48,58 @@ public function resolve( ResolveInfo $info, array $value = null, array $args = null - ) : Value { - $result = function () { - return null; - }; - - if (isset($args['url'])) { - $url = $args['url']; - if (substr($url, 0, 1) === '/' && $url !== '/') { - $url = ltrim($url, '/'); - } - $customUrl = $this->customUrlLocator->locateUrl($url); - $url = $customUrl ?: $url; - $urlRewrite = $this->findCanonicalUrl($url); - if ($urlRewrite) { - $urlRewriteReturnArray = [ - 'id' => $urlRewrite->getEntityId(), - 'canonical_url' => $urlRewrite->getTargetPath(), - 'type' => $this->sanitizeType($urlRewrite->getEntityType()) - ]; - $result = function () use ($urlRewriteReturnArray) { - return $urlRewriteReturnArray; - }; - } + ): Value { + if (!isset($value['model'])) { + $result = function () { + return null; + }; + return $this->valueFactory->create($result); } - return $this->valueFactory->create($result); - } - /** - * Find the canonical url passing through all redirects if any - * - * @param string $requestPath - * @return \Magento\UrlRewrite\Service\V1\Data\UrlRewrite|null - */ - private function findCanonicalUrl(string $requestPath) : ?\Magento\UrlRewrite\Service\V1\Data\UrlRewrite - { - $urlRewrite = $this->findUrlFromRequestPath($requestPath); - if ($urlRewrite && $urlRewrite->getRedirectType() > 0) { - while ($urlRewrite && $urlRewrite->getRedirectType() > 0) { - $urlRewrite = $this->findUrlFromRequestPath($urlRewrite->getTargetPath()); + /** @var AbstractModel $entity */ + $entity = $value['model']; + $entityId = $entity->getEntityId(); + + $urlRewritesCollection = $this->urlFinder->findAllByData([UrlRewriteDTO::ENTITY_ID => $entityId]); + $urlRewrites = []; + + /** @var UrlRewriteDTO $urlRewrite */ + foreach ($urlRewritesCollection as $urlRewrite) { + if ($urlRewrite->getRedirectType() !== 0) { + continue; } + + $urlRewrites[] = [ + 'url' => $urlRewrite->getRequestPath(), + 'parameters' => $this->getUrlParameters($urlRewrite->getTargetPath()) + ]; } - if (!$urlRewrite) { - $urlRewrite = $this->findUrlFromTargetPath($requestPath); - } - - return $urlRewrite; - } - /** - * Find a url from a request url on the current store - * - * @param string $requestPath - * @return \Magento\UrlRewrite\Service\V1\Data\UrlRewrite|null - */ - private function findUrlFromRequestPath(string $requestPath) : ?\Magento\UrlRewrite\Service\V1\Data\UrlRewrite - { - return $this->urlFinder->findOneByData( - [ - 'request_path' => $requestPath, - 'store_id' => $this->storeManager->getStore()->getId() - ] - ); + $result = function () use ($urlRewrites) { + return $urlRewrites; + }; + + return $this->valueFactory->create($result); } /** - * Find a url from a target url on the current store + * Parses target path and extracts parameters * * @param string $targetPath - * @return \Magento\UrlRewrite\Service\V1\Data\UrlRewrite|null + * @return array */ - private function findUrlFromTargetPath(string $targetPath) : ?\Magento\UrlRewrite\Service\V1\Data\UrlRewrite + private function getUrlParameters(string $targetPath): array { - return $this->urlFinder->findOneByData( - [ - 'target_path' => $targetPath, - 'store_id' => $this->storeManager->getStore()->getId() - ] - ); - } + $urlParameters = []; + $targetPathParts = explode('/', trim($targetPath, '/')); - /** - * Sanitize the type to fit schema specifications - * - * @param string $type - * @return string - */ - private function sanitizeType(string $type) : string - { - return strtoupper(str_replace('-', '_', $type)); + for ($i = 3; ($i < sizeof($targetPathParts) - 1); $i += 2) { + $urlParameters[] = [ + 'name' => $targetPathParts[$i], + 'value' => $targetPathParts[$i + 1] + ]; + } + + return $urlParameters; } } diff --git a/app/code/Magento/UrlRewriteGraphQl/etc/schema.graphqls b/app/code/Magento/UrlRewriteGraphQl/etc/schema.graphqls index 38f1d9c65637c..a0d7a27ffa3da 100644 --- a/app/code/Magento/UrlRewriteGraphQl/etc/schema.graphqls +++ b/app/code/Magento/UrlRewriteGraphQl/etc/schema.graphqls @@ -8,8 +8,18 @@ type EntityUrl @doc(description: "EntityUrl is an output object containing the ` } type Query { - urlResolver(url: String!): EntityUrl @resolver(class: "Magento\\UrlRewriteGraphQl\\Model\\Resolver\\UrlRewrite") @doc(description: "The urlResolver query returns the canonical URL for a specified product, category or CMS page") + urlResolver(url: String!): EntityUrl @resolver(class: "Magento\\UrlRewriteGraphQl\\Model\\Resolver\\EntityUrl") @doc(description: "The urlResolver query returns the canonical URL for a specified product, category or CMS page") } enum UrlRewriteEntityTypeEnum { } + +type UrlRewrite @doc(description: "The object contains URL rewrite details") { + url: String @doc(description: "Request URL") + parameters: [HttpQueryParameter] @doc(description: "Request parameters") +} + +type HttpQueryParameter @doc(description: "The object details of target path parameters") { + name: String @doc(description: "Parameter name") + value: String @doc(description: "Parameter value") +} From 46a871ed6ff6ad13358db1867283b93bcbc2ee67 Mon Sep 17 00:00:00 2001 From: Yaroslav Rogoza Date: Thu, 19 Jul 2018 18:29:22 +0200 Subject: [PATCH 02/10] Api-functional test for product with no categories --- .../Model/Resolver/UrlRewrite.php | 4 + .../GraphQl/Catalog/UrlRewritesTest.php | 119 ++++++++++++++++++ 2 files changed, 123 insertions(+) create mode 100644 dev/tests/api-functional/testsuite/Magento/GraphQl/Catalog/UrlRewritesTest.php diff --git a/app/code/Magento/UrlRewriteGraphQl/Model/Resolver/UrlRewrite.php b/app/code/Magento/UrlRewriteGraphQl/Model/Resolver/UrlRewrite.php index e64912d171a63..7e1b31090850b 100644 --- a/app/code/Magento/UrlRewriteGraphQl/Model/Resolver/UrlRewrite.php +++ b/app/code/Magento/UrlRewriteGraphQl/Model/Resolver/UrlRewrite.php @@ -21,7 +21,11 @@ */ class UrlRewrite implements ResolverInterface { + /** + * @var UrlFinderInterface + */ private $urlFinder; + /** * @var ValueFactory */ diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Catalog/UrlRewritesTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Catalog/UrlRewritesTest.php new file mode 100644 index 0000000000000..a22ec7b639346 --- /dev/null +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Catalog/UrlRewritesTest.php @@ -0,0 +1,119 @@ +graphQlQuery($query); + + /** @var ProductRepositoryInterface $productRepository */ + $productRepository = ObjectManager::getInstance()->get(ProductRepositoryInterface::class); + $product = $productRepository->get('virtual-product', false, null, true); + + $urlFinder = ObjectManager::getInstance()->get(UrlFinderInterface::class); + + $rewritesCollection = $urlFinder->findAllByData([UrlRewriteDTO::ENTITY_ID => $product->getId()]); + + /* There should be only one rewrite */ + /** @var UrlRewriteDTO $urlRewrite */ + $urlRewrite = current($rewritesCollection); + + $this->assertArrayHasKey('url_rewrites', $response['products']['items'][0]); + $this->assertCount(1, $response['products']['items'][0]['url_rewrites']); + + $this->assertResponseFields( + $response['products']['items'][0]['url_rewrites'][0], + [ + "url" => $urlRewrite->getRequestPath(), + "parameters" => $this->getUrlParameters($urlRewrite->getTargetPath()) + ] + ); + } + + /** + * Parses target path and extracts parameters + * + * @param string $targetPath + * @return array + */ + private function getUrlParameters(string $targetPath): array + { + $urlParameters = []; + $targetPathParts = explode('/', trim($targetPath, '/')); + + for ($i = 3; ($i < sizeof($targetPathParts) - 1); $i += 2) { + $urlParameters[] = [ + 'name' => $targetPathParts[$i], + 'value' => $targetPathParts[$i + 1] + ]; + } + + return $urlParameters; + } + + /** + * @param array $actualResponse + * @param array $assertionMap + */ + private function assertResponseFields($actualResponse, $assertionMap) + { + foreach ($assertionMap as $key => $assertionData) { + $expectedValue = isset($assertionData['expected_value']) + ? $assertionData['expected_value'] + : $assertionData; + $responseField = isset($assertionData['response_field']) ? $assertionData['response_field'] : $key; + self::assertNotNull( + $expectedValue, + "Value of '{$responseField}' field must not be NULL" + ); + self::assertEquals( + $expectedValue, + $actualResponse[$responseField], + "Value of '{$responseField}' field in response does not match expected value: " + . var_export($expectedValue, true) + ); + } + } +} From dfabfe5c24ff833d96e35d5088fc236525fad0c8 Mon Sep 17 00:00:00 2001 From: Yaroslav Rogoza Date: Fri, 20 Jul 2018 10:08:00 +0200 Subject: [PATCH 03/10] Api-functional test for product with categories --- .../GraphQl/Catalog/UrlRewritesTest.php | 56 ++++++++++++++++++- 1 file changed, 55 insertions(+), 1 deletion(-) diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Catalog/UrlRewritesTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Catalog/UrlRewritesTest.php index a22ec7b639346..0d680d1a65482 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Catalog/UrlRewritesTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Catalog/UrlRewritesTest.php @@ -14,7 +14,7 @@ use Magento\UrlRewrite\Service\V1\Data\UrlRewrite as UrlRewriteDTO; /** - * Test of getting child products info of configurable product on category request + * Test of getting URL rewrites data from products */ class UrlRewritesTest extends GraphQlAbstract { @@ -72,6 +72,60 @@ public function testProductWithNoCategoriesAssigned() ); } + /** + * + * @magentoApiDataFixture Magento/Catalog/_files/product_simple.php + * @throws \Magento\Framework\Exception\NoSuchEntityException + */ + public function testProductWithOneCategoryAssigned() + { + + $query + = <<graphQlQuery($query); + + /** @var ProductRepositoryInterface $productRepository */ + $productRepository = ObjectManager::getInstance()->get(ProductRepositoryInterface::class); + $product = $productRepository->get('simple', false, null, true); + + $urlFinder = ObjectManager::getInstance()->get(UrlFinderInterface::class); + + $rewritesCollection = $urlFinder->findAllByData([UrlRewriteDTO::ENTITY_ID => $product->getId()]); + $rewritesCount = count($rewritesCollection); + + $this->assertArrayHasKey('url_rewrites', $response['products']['items'][0]); + $this->assertCount($rewritesCount, $response['products']['items'][0]['url_rewrites']); + + for ($i = 0; $i < $rewritesCount; $i++) { + $urlRewrite = $rewritesCollection[$i]; + $this->assertResponseFields( + $response['products']['items'][0]['url_rewrites'][$i], + [ + "url" => $urlRewrite->getRequestPath(), + "parameters" => $this->getUrlParameters($urlRewrite->getTargetPath()) + ] + ); + } + } + /** * Parses target path and extracts parameters * From e0f41322856906680134d714229ca48a5a7a6d34 Mon Sep 17 00:00:00 2001 From: Yaroslav Rogoza Date: Wed, 5 Sep 2018 14:40:42 +0200 Subject: [PATCH 04/10] url_rewrites attribute moved to UrlRewriteGraphQl module --- app/code/Magento/CatalogGraphQl/etc/schema.graphqls | 3 +-- .../UrlRewriteGraphQl/Model/Resolver/EntityUrl.php | 8 ++++---- .../UrlRewriteGraphQl/Model/Resolver/UrlRewrite.php | 4 ++-- app/code/Magento/UrlRewriteGraphQl/etc/schema.graphqls | 4 ++++ 4 files changed, 11 insertions(+), 8 deletions(-) diff --git a/app/code/Magento/CatalogGraphQl/etc/schema.graphqls b/app/code/Magento/CatalogGraphQl/etc/schema.graphqls index b7a5f7ac1c640..d7b9da59380fd 100644 --- a/app/code/Magento/CatalogGraphQl/etc/schema.graphqls +++ b/app/code/Magento/CatalogGraphQl/etc/schema.graphqls @@ -280,7 +280,6 @@ interface ProductInterface @typeResolver(class: "Magento\\CatalogGraphQl\\Model\ manufacturer: Int @doc(description: "A number representing the product's manufacturer") categories: [CategoryInterface] @doc(description: "The categories assigned to a product") @resolver(class: "Magento\\CatalogGraphQl\\Model\\Resolver\\Categories") canonical_url: String @doc(description: "Canonical URL") @resolver(class: "Magento\\CatalogGraphQl\\Model\\Resolver\\Product\\CanonicalUrl") - url_rewrites: [UrlRewrite] @doc(description: "URL rewrites list") @resolver(class: "Magento\\UrlRewriteGraphQl\\Model\\Resolver\\UrlRewrite") } interface PhysicalProductInterface @typeResolver(class: "Magento\\CatalogGraphQl\\Model\\ProductInterfaceTypeResolverComposite") @doc(description: "PhysicalProductInterface contains attributes specific to tangible products") { @@ -541,6 +540,6 @@ type SortField { } type SortFields @doc(description: "SortFields contains a default value for sort fields and all available sort fields") { - default: String @doc(description: "Default value of sort fields") + default: String @doc(description: "Default value of sort fields") options: [SortField] @doc(description: "Available sort fields") } diff --git a/app/code/Magento/UrlRewriteGraphQl/Model/Resolver/EntityUrl.php b/app/code/Magento/UrlRewriteGraphQl/Model/Resolver/EntityUrl.php index 9790339dd10c6..58557b6aa5c02 100644 --- a/app/code/Magento/UrlRewriteGraphQl/Model/Resolver/EntityUrl.php +++ b/app/code/Magento/UrlRewriteGraphQl/Model/Resolver/EntityUrl.php @@ -17,7 +17,7 @@ use Magento\UrlRewriteGraphQl\Model\Resolver\UrlRewrite\CustomUrlLocatorInterface; /** - * UrlRewrite field resolver, used for GraphQL request processing. + * The resolver returns the canonical URL for a specified product, category or CMS page */ class EntityUrl implements ResolverInterface { @@ -35,7 +35,7 @@ class EntityUrl implements ResolverInterface * @var ValueFactory */ private $valueFactory; - + /** * @var CustomUrlLocatorInterface */ @@ -72,7 +72,7 @@ public function resolve( $result = function () { return null; }; - + if (isset($args['url'])) { $url = $args['url']; if (substr($url, 0, 1) === '/' && $url !== '/') { @@ -112,7 +112,7 @@ private function findCanonicalUrl(string $requestPath) : ?\Magento\UrlRewrite\Se if (!$urlRewrite) { $urlRewrite = $this->findUrlFromTargetPath($requestPath); } - + return $urlRewrite; } diff --git a/app/code/Magento/UrlRewriteGraphQl/Model/Resolver/UrlRewrite.php b/app/code/Magento/UrlRewriteGraphQl/Model/Resolver/UrlRewrite.php index 7e1b31090850b..fc502422288a8 100644 --- a/app/code/Magento/UrlRewriteGraphQl/Model/Resolver/UrlRewrite.php +++ b/app/code/Magento/UrlRewriteGraphQl/Model/Resolver/UrlRewrite.php @@ -17,7 +17,7 @@ use Magento\UrlRewrite\Service\V1\Data\UrlRewrite as UrlRewriteDTO; /** - * UrlRewrite field resolver, used for GraphQL request processing. + * Returns URL rewrites list for the specified product */ class UrlRewrite implements ResolverInterface { @@ -63,7 +63,7 @@ public function resolve( /** @var AbstractModel $entity */ $entity = $value['model']; $entityId = $entity->getEntityId(); - + $urlRewritesCollection = $this->urlFinder->findAllByData([UrlRewriteDTO::ENTITY_ID => $entityId]); $urlRewrites = []; diff --git a/app/code/Magento/UrlRewriteGraphQl/etc/schema.graphqls b/app/code/Magento/UrlRewriteGraphQl/etc/schema.graphqls index a0d7a27ffa3da..fc6e68c0e8dbb 100644 --- a/app/code/Magento/UrlRewriteGraphQl/etc/schema.graphqls +++ b/app/code/Magento/UrlRewriteGraphQl/etc/schema.graphqls @@ -23,3 +23,7 @@ type HttpQueryParameter @doc(description: "The object details of target path par name: String @doc(description: "Parameter name") value: String @doc(description: "Parameter value") } + +interface ProductInterface { + url_rewrites: [UrlRewrite] @doc(description: "URL rewrites list") @resolver(class: "Magento\\UrlRewriteGraphQl\\Model\\Resolver\\UrlRewrite") +} \ No newline at end of file From e9a06a6396db713d7de881f3c145073bacc7c948 Mon Sep 17 00:00:00 2001 From: Yaroslav Rogoza Date: Wed, 5 Sep 2018 14:50:02 +0200 Subject: [PATCH 05/10] API-functional tests improvements --- .../testsuite/Magento/GraphQl/Catalog/UrlRewritesTest.php | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Catalog/UrlRewritesTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Catalog/UrlRewritesTest.php index 0d680d1a65482..e8611498d2ee5 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Catalog/UrlRewritesTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Catalog/UrlRewritesTest.php @@ -25,11 +25,11 @@ class UrlRewritesTest extends GraphQlAbstract */ public function testProductWithNoCategoriesAssigned() { - + $productSku = 'virtual-product'; $query = << Date: Tue, 18 Sep 2018 17:07:29 +0200 Subject: [PATCH 06/10] Remove value factory. Return value directly --- .../Model/Resolver/EntityUrl.php | 57 +++++++------------ .../Model/Resolver/UrlRewrite.php | 30 +++------- .../GraphQl/Catalog/UrlRewritesTest.php | 24 -------- 3 files changed, 29 insertions(+), 82 deletions(-) diff --git a/app/code/Magento/UrlRewriteGraphQl/Model/Resolver/EntityUrl.php b/app/code/Magento/UrlRewriteGraphQl/Model/Resolver/EntityUrl.php index 58557b6aa5c02..1c25ffd1e9ff7 100644 --- a/app/code/Magento/UrlRewriteGraphQl/Model/Resolver/EntityUrl.php +++ b/app/code/Magento/UrlRewriteGraphQl/Model/Resolver/EntityUrl.php @@ -7,17 +7,16 @@ namespace Magento\UrlRewriteGraphQl\Model\Resolver; +use Magento\Framework\GraphQl\Exception\GraphQlInputException; use Magento\Framework\GraphQl\Schema\Type\ResolveInfo; use Magento\Framework\GraphQl\Config\Element\Field; -use Magento\Framework\GraphQl\Query\Resolver\Value; -use Magento\Framework\GraphQl\Query\Resolver\ValueFactory; use Magento\Framework\GraphQl\Query\ResolverInterface; use Magento\Store\Model\StoreManagerInterface; use Magento\UrlRewrite\Model\UrlFinderInterface; use Magento\UrlRewriteGraphQl\Model\Resolver\UrlRewrite\CustomUrlLocatorInterface; /** - * The resolver returns the canonical URL for a specified product, category or CMS page + * UrlRewrite field resolver, used for GraphQL request processing. */ class EntityUrl implements ResolverInterface { @@ -31,11 +30,6 @@ class EntityUrl implements ResolverInterface */ private $storeManager; - /** - * @var ValueFactory - */ - private $valueFactory; - /** * @var CustomUrlLocatorInterface */ @@ -44,23 +38,20 @@ class EntityUrl implements ResolverInterface /** * @param UrlFinderInterface $urlFinder * @param StoreManagerInterface $storeManager - * @param ValueFactory $valueFactory * @param CustomUrlLocatorInterface $customUrlLocator */ public function __construct( UrlFinderInterface $urlFinder, StoreManagerInterface $storeManager, - ValueFactory $valueFactory, CustomUrlLocatorInterface $customUrlLocator ) { $this->urlFinder = $urlFinder; $this->storeManager = $storeManager; - $this->valueFactory = $valueFactory; $this->customUrlLocator = $customUrlLocator; } /** - * {@inheritdoc} + * @inheritdoc */ public function resolve( Field $field, @@ -68,31 +59,27 @@ public function resolve( ResolveInfo $info, array $value = null, array $args = null - ) : Value { - $result = function () { - return null; - }; + ) { + if (!isset($args['url']) || empty(trim($args['url']))) { + throw new GraphQlInputException(__('"url" argument should be specified and not empty')); + } - if (isset($args['url'])) { - $url = $args['url']; - if (substr($url, 0, 1) === '/' && $url !== '/') { - $url = ltrim($url, '/'); - } - $customUrl = $this->customUrlLocator->locateUrl($url); - $url = $customUrl ?: $url; - $urlRewrite = $this->findCanonicalUrl($url); - if ($urlRewrite) { - $urlRewriteReturnArray = [ - 'id' => $urlRewrite->getEntityId(), - 'canonical_url' => $urlRewrite->getTargetPath(), - 'type' => $this->sanitizeType($urlRewrite->getEntityType()) - ]; - $result = function () use ($urlRewriteReturnArray) { - return $urlRewriteReturnArray; - }; - } + $result = null; + $url = $args['url']; + if (substr($url, 0, 1) === '/' && $url !== '/') { + $url = ltrim($url, '/'); + } + $customUrl = $this->customUrlLocator->locateUrl($url); + $url = $customUrl ?: $url; + $urlRewrite = $this->findCanonicalUrl($url); + if ($urlRewrite) { + $result = [ + 'id' => $urlRewrite->getEntityId(), + 'canonical_url' => $urlRewrite->getTargetPath(), + 'type' => $this->sanitizeType($urlRewrite->getEntityType()) + ]; } - return $this->valueFactory->create($result); + return $result; } /** diff --git a/app/code/Magento/UrlRewriteGraphQl/Model/Resolver/UrlRewrite.php b/app/code/Magento/UrlRewriteGraphQl/Model/Resolver/UrlRewrite.php index fc502422288a8..0c4c78b582941 100644 --- a/app/code/Magento/UrlRewriteGraphQl/Model/Resolver/UrlRewrite.php +++ b/app/code/Magento/UrlRewriteGraphQl/Model/Resolver/UrlRewrite.php @@ -7,10 +7,9 @@ namespace Magento\UrlRewriteGraphQl\Model\Resolver; +use Magento\Framework\GraphQl\Exception\GraphQlInputException; use Magento\Framework\GraphQl\Schema\Type\ResolveInfo; use Magento\Framework\GraphQl\Config\Element\Field; -use Magento\Framework\GraphQl\Query\Resolver\Value; -use Magento\Framework\GraphQl\Query\Resolver\ValueFactory; use Magento\Framework\GraphQl\Query\ResolverInterface; use Magento\Framework\Model\AbstractModel; use Magento\UrlRewrite\Model\UrlFinderInterface; @@ -27,24 +26,16 @@ class UrlRewrite implements ResolverInterface private $urlFinder; /** - * @var ValueFactory - */ - private $valueFactory; - - /** - * @param ValueFactory $valueFactory * @param UrlFinderInterface $urlFinder */ public function __construct( - ValueFactory $valueFactory, UrlFinderInterface $urlFinder ) { - $this->valueFactory = $valueFactory; $this->urlFinder = $urlFinder; } /** - * {@inheritdoc} + * @inheritdoc */ public function resolve( Field $field, @@ -52,23 +43,20 @@ public function resolve( ResolveInfo $info, array $value = null, array $args = null - ): Value { + ): array { if (!isset($value['model'])) { - $result = function () { - return null; - }; - return $this->valueFactory->create($result); + throw new GraphQlInputException(__('"model" value should be specified')); } /** @var AbstractModel $entity */ $entity = $value['model']; $entityId = $entity->getEntityId(); - $urlRewritesCollection = $this->urlFinder->findAllByData([UrlRewriteDTO::ENTITY_ID => $entityId]); + $urlRewriteCollection = $this->urlFinder->findAllByData([UrlRewriteDTO::ENTITY_ID => $entityId]); $urlRewrites = []; /** @var UrlRewriteDTO $urlRewrite */ - foreach ($urlRewritesCollection as $urlRewrite) { + foreach ($urlRewriteCollection as $urlRewrite) { if ($urlRewrite->getRedirectType() !== 0) { continue; } @@ -79,11 +67,7 @@ public function resolve( ]; } - $result = function () use ($urlRewrites) { - return $urlRewrites; - }; - - return $this->valueFactory->create($result); + return $urlRewrites; } /** diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Catalog/UrlRewritesTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Catalog/UrlRewritesTest.php index e8611498d2ee5..c39b32e4bfa4f 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Catalog/UrlRewritesTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Catalog/UrlRewritesTest.php @@ -146,28 +146,4 @@ private function getUrlParameters(string $targetPath): array return $urlParameters; } - - /** - * @param array $actualResponse - * @param array $assertionMap - */ - private function assertResponseFields($actualResponse, $assertionMap) - { - foreach ($assertionMap as $key => $assertionData) { - $expectedValue = isset($assertionData['expected_value']) - ? $assertionData['expected_value'] - : $assertionData; - $responseField = isset($assertionData['response_field']) ? $assertionData['response_field'] : $key; - self::assertNotNull( - $expectedValue, - "Value of '{$responseField}' field must not be NULL" - ); - self::assertEquals( - $expectedValue, - $actualResponse[$responseField], - "Value of '{$responseField}' field in response does not match expected value: " - . var_export($expectedValue, true) - ); - } - } } From e2cad8915ce3d5394e51c9c48e948ab94d9eda7a Mon Sep 17 00:00:00 2001 From: Yaroslav Rogoza Date: Wed, 26 Sep 2018 15:01:23 +0200 Subject: [PATCH 07/10] Fix schema definitions after resolving the conflict --- app/code/Magento/UrlRewriteGraphQl/etc/schema.graphqls | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/app/code/Magento/UrlRewriteGraphQl/etc/schema.graphqls b/app/code/Magento/UrlRewriteGraphQl/etc/schema.graphqls index 61e76ae035fa0..933d9a2d7247b 100644 --- a/app/code/Magento/UrlRewriteGraphQl/etc/schema.graphqls +++ b/app/code/Magento/UrlRewriteGraphQl/etc/schema.graphqls @@ -8,8 +8,7 @@ type EntityUrl @doc(description: "EntityUrl is an output object containing the ` } type Query { - urlResolver(url: String!): EntityUrl @resolver(class: "Magento\\UrlRewriteGraphQl\\Model\\Resolver\\UrlRewrite") @doc(description: "The urlResolver query returns the relative URL for a specified product, category or CMS page") - urlResolver(url: String!): EntityUrl @resolver(class: "Magento\\UrlRewriteGraphQl\\Model\\Resolver\\EntityUrl") @doc(description: "The urlResolver query returns the canonical URL for a specified product, category or CMS page") + urlResolver(url: String!): EntityUrl @resolver(class: "Magento\\UrlRewriteGraphQl\\Model\\Resolver\\EntityUrl") @doc(description: "The urlResolver query returns the relative URL for a specified product, category or CMS page") } enum UrlRewriteEntityTypeEnum { From 987b138cb301f776594ce099b7c878c83b434179 Mon Sep 17 00:00:00 2001 From: Valeriy Nayda Date: Mon, 1 Oct 2018 14:36:49 +0300 Subject: [PATCH 08/10] GraphQL-84: Return URL Rewrites for products --- app/code/Magento/CatalogGraphQl/etc/module.xml | 1 - app/code/Magento/CatalogUrlRewriteGraphQl/etc/schema.graphqls | 1 + app/code/Magento/UrlRewriteGraphQl/etc/schema.graphqls | 4 ---- 3 files changed, 1 insertion(+), 5 deletions(-) diff --git a/app/code/Magento/CatalogGraphQl/etc/module.xml b/app/code/Magento/CatalogGraphQl/etc/module.xml index 2551664cc5f62..87696c129a714 100644 --- a/app/code/Magento/CatalogGraphQl/etc/module.xml +++ b/app/code/Magento/CatalogGraphQl/etc/module.xml @@ -15,7 +15,6 @@ - diff --git a/app/code/Magento/CatalogUrlRewriteGraphQl/etc/schema.graphqls b/app/code/Magento/CatalogUrlRewriteGraphQl/etc/schema.graphqls index b96cfcb03d41f..f4ad2e930ddab 100644 --- a/app/code/Magento/CatalogUrlRewriteGraphQl/etc/schema.graphqls +++ b/app/code/Magento/CatalogUrlRewriteGraphQl/etc/schema.graphqls @@ -4,6 +4,7 @@ interface ProductInterface { url_key: String @doc(description: "The part of the URL that identifies the product") url_path: String @doc(description: "The part of the URL that precedes the url_key") + url_rewrites: [UrlRewrite] @doc(description: "URL rewrites list") @resolver(class: "Magento\\UrlRewriteGraphQl\\Model\\Resolver\\UrlRewrite") } input ProductFilterInput { diff --git a/app/code/Magento/UrlRewriteGraphQl/etc/schema.graphqls b/app/code/Magento/UrlRewriteGraphQl/etc/schema.graphqls index 933d9a2d7247b..dae695c69a33c 100644 --- a/app/code/Magento/UrlRewriteGraphQl/etc/schema.graphqls +++ b/app/code/Magento/UrlRewriteGraphQl/etc/schema.graphqls @@ -23,7 +23,3 @@ type HttpQueryParameter @doc(description: "The object details of target path par name: String @doc(description: "Parameter name") value: String @doc(description: "Parameter value") } - -interface ProductInterface { - url_rewrites: [UrlRewrite] @doc(description: "URL rewrites list") @resolver(class: "Magento\\UrlRewriteGraphQl\\Model\\Resolver\\UrlRewrite") -} \ No newline at end of file From 0fe1ae57e55f5e97c4b22709799033a73e4f457c Mon Sep 17 00:00:00 2001 From: Valeriy Nayda Date: Mon, 1 Oct 2018 19:13:34 +0300 Subject: [PATCH 09/10] GraphQL-84: Return URL Rewrites for products --- app/code/Magento/CatalogUrlRewriteGraphQl/etc/module.xml | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/app/code/Magento/CatalogUrlRewriteGraphQl/etc/module.xml b/app/code/Magento/CatalogUrlRewriteGraphQl/etc/module.xml index be4bb9fcd7010..e6e0f6cf72100 100644 --- a/app/code/Magento/CatalogUrlRewriteGraphQl/etc/module.xml +++ b/app/code/Magento/CatalogUrlRewriteGraphQl/etc/module.xml @@ -6,5 +6,10 @@ */ --> - + + + + + + From 7b8799d5a9f71a5d8851698ff1d4e38b1146bba9 Mon Sep 17 00:00:00 2001 From: Valeriy Nayda Date: Wed, 3 Oct 2018 16:24:59 +0300 Subject: [PATCH 10/10] GraphQL-84: Return URL Rewrites for products --- .../GraphQl/UrlRewrite/UrlResolverTest.php | 34 +++++++++---------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/UrlRewrite/UrlResolverTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/UrlRewrite/UrlResolverTest.php index 370121a1dad78..c70b1631e85cd 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/UrlRewrite/UrlResolverTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/UrlRewrite/UrlResolverTest.php @@ -31,7 +31,7 @@ protected function setUp() } /** - * Tests if target_path(relative_url) is resolved for Product entity + * Tests if target_path(canonical_url) is resolved for Product entity * * @magentoApiDataFixture Magento/CatalogUrlRewrite/_files/product_with_category.php */ @@ -60,7 +60,7 @@ public function testProductUrlResolver() urlResolver(url:"{$urlPath}") { id - relative_url + canonical_url type } } @@ -68,12 +68,12 @@ public function testProductUrlResolver() $response = $this->graphQlQuery($query); $this->assertArrayHasKey('urlResolver', $response); $this->assertEquals($product->getEntityId(), $response['urlResolver']['id']); - $this->assertEquals($targetPath, $response['urlResolver']['relative_url']); + $this->assertEquals($targetPath, $response['urlResolver']['canonical_url']); $this->assertEquals(strtoupper($expectedType), $response['urlResolver']['type']); } /** - * Tests the use case where relative_url is provided as resolver input in the Query + * Tests the use case where canonical_url is provided as resolver input in the Query * * @magentoApiDataFixture Magento/CatalogUrlRewrite/_files/product_with_category.php */ @@ -104,7 +104,7 @@ public function testProductUrlWithCanonicalUrlInput() urlResolver(url:"{$canonicalPath}") { id - relative_url + canonical_url type } } @@ -112,7 +112,7 @@ public function testProductUrlWithCanonicalUrlInput() $response = $this->graphQlQuery($query); $this->assertArrayHasKey('urlResolver', $response); $this->assertEquals($product->getEntityId(), $response['urlResolver']['id']); - $this->assertEquals($targetPath, $response['urlResolver']['relative_url']); + $this->assertEquals($targetPath, $response['urlResolver']['canonical_url']); $this->assertEquals(strtoupper($expectedType), $response['urlResolver']['type']); } @@ -147,7 +147,7 @@ public function testCategoryUrlResolver() urlResolver(url:"{$urlPath2}") { id - relative_url + canonical_url type } } @@ -155,7 +155,7 @@ public function testCategoryUrlResolver() $response = $this->graphQlQuery($query); $this->assertArrayHasKey('urlResolver', $response); $this->assertEquals($categoryId, $response['urlResolver']['id']); - $this->assertEquals($targetPath, $response['urlResolver']['relative_url']); + $this->assertEquals($targetPath, $response['urlResolver']['canonical_url']); $this->assertEquals(strtoupper($expectedType), $response['urlResolver']['type']); } @@ -183,14 +183,14 @@ public function testCMSPageUrlResolver() urlResolver(url:"{$requestPath}") { id - relative_url + canonical_url type } } QUERY; $response = $this->graphQlQuery($query); $this->assertEquals($cmsPageId, $response['urlResolver']['id']); - $this->assertEquals($targetPath, $response['urlResolver']['relative_url']); + $this->assertEquals($targetPath, $response['urlResolver']['canonical_url']); $this->assertEquals(strtoupper(str_replace('-', '_', $expectedEntityType)), $response['urlResolver']['type']); } @@ -226,7 +226,7 @@ public function testProductUrlRewriteResolver() urlResolver(url:"{$urlPath}") { id - relative_url + canonical_url type } } @@ -234,7 +234,7 @@ public function testProductUrlRewriteResolver() $response = $this->graphQlQuery($query); $this->assertArrayHasKey('urlResolver', $response); $this->assertEquals($product->getEntityId(), $response['urlResolver']['id']); - $this->assertEquals($targetPath, $response['urlResolver']['relative_url']); + $this->assertEquals($targetPath, $response['urlResolver']['canonical_url']); $this->assertEquals(strtoupper($expectedType), $response['urlResolver']['type']); } @@ -266,7 +266,7 @@ public function testInvalidUrlResolverInput() urlResolver(url:"{$urlPath}") { id - relative_url + canonical_url type } } @@ -307,7 +307,7 @@ public function testCategoryUrlWithLeadingSlash() urlResolver(url:"/{$urlPath}") { id - relative_url + canonical_url type } } @@ -315,7 +315,7 @@ public function testCategoryUrlWithLeadingSlash() $response = $this->graphQlQuery($query); $this->assertArrayHasKey('urlResolver', $response); $this->assertEquals($categoryId, $response['urlResolver']['id']); - $this->assertEquals($targetPath, $response['urlResolver']['relative_url']); + $this->assertEquals($targetPath, $response['urlResolver']['canonical_url']); $this->assertEquals(strtoupper($expectedType), $response['urlResolver']['type']); } @@ -344,7 +344,7 @@ public function testResolveSlash() urlResolver(url:"/") { id - relative_url + canonical_url type } } @@ -352,7 +352,7 @@ public function testResolveSlash() $response = $this->graphQlQuery($query); $this->assertArrayHasKey('urlResolver', $response); $this->assertEquals($homePageId, $response['urlResolver']['id']); - $this->assertEquals($targetPath, $response['urlResolver']['relative_url']); + $this->assertEquals($targetPath, $response['urlResolver']['canonical_url']); $this->assertEquals('CMS_PAGE', $response['urlResolver']['type']); } }