Skip to content

Commit b96a844

Browse files
ENGCOM-3072: Added URL rewrites data to the product interface #107
- Merge Pull Request magento/graphql-ce#107 from magento/graphql-ce:product-url-rewrites - Merged commits: 1. d6d0872 2. b583ee7 3. 57c2e4c 4. 46a871e 5. dfabfe5 6. e0f4132 7. e9a06a6 8. b062bd9 9. 1700740 10. f141a0d 11. e2cad89 12. 16b72a8 13. df3360b 14. 987b138 15. 0fe1ae5 16. 7b8799d 17. 6d8e43d
2 parents da5a9ed + 6d8e43d commit b96a844

File tree

7 files changed

+370
-112
lines changed

7 files changed

+370
-112
lines changed

app/code/Magento/CatalogUrlRewriteGraphQl/etc/module.xml

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,5 +6,10 @@
66
*/
77
-->
88
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Module/etc/module.xsd">
9-
<module name="Magento_CatalogUrlRewriteGraphQl" />
9+
<module name="Magento_CatalogUrlRewriteGraphQl" >
10+
<sequence>
11+
<module name="Magento_UrlRewriteGraphQl"/>
12+
<module name="Magento_CatalogGraphQl"/>
13+
</sequence>
14+
</module>
1015
</config>

app/code/Magento/CatalogUrlRewriteGraphQl/etc/schema.graphqls

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
interface ProductInterface {
55
url_key: String @doc(description: "The part of the URL that identifies the product")
66
url_path: String @doc(description: "The part of the URL that precedes the url_key")
7+
url_rewrites: [UrlRewrite] @doc(description: "URL rewrites list") @resolver(class: "Magento\\UrlRewriteGraphQl\\Model\\Resolver\\UrlRewrite")
78
}
89

910
input ProductFilterInput {
Lines changed: 148 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,148 @@
1+
<?php
2+
/**
3+
* Copyright © Magento, Inc. All rights reserved.
4+
* See COPYING.txt for license details.
5+
*/
6+
declare(strict_types=1);
7+
8+
namespace Magento\UrlRewriteGraphQl\Model\Resolver;
9+
10+
use Magento\Framework\GraphQl\Exception\GraphQlInputException;
11+
use Magento\Framework\GraphQl\Schema\Type\ResolveInfo;
12+
use Magento\Framework\GraphQl\Config\Element\Field;
13+
use Magento\Framework\GraphQl\Query\ResolverInterface;
14+
use Magento\Store\Model\StoreManagerInterface;
15+
use Magento\UrlRewrite\Model\UrlFinderInterface;
16+
use Magento\UrlRewriteGraphQl\Model\Resolver\UrlRewrite\CustomUrlLocatorInterface;
17+
18+
/**
19+
* UrlRewrite field resolver, used for GraphQL request processing.
20+
*/
21+
class EntityUrl implements ResolverInterface
22+
{
23+
/**
24+
* @var UrlFinderInterface
25+
*/
26+
private $urlFinder;
27+
28+
/**
29+
* @var StoreManagerInterface
30+
*/
31+
private $storeManager;
32+
33+
/**
34+
* @var CustomUrlLocatorInterface
35+
*/
36+
private $customUrlLocator;
37+
38+
/**
39+
* @param UrlFinderInterface $urlFinder
40+
* @param StoreManagerInterface $storeManager
41+
* @param CustomUrlLocatorInterface $customUrlLocator
42+
*/
43+
public function __construct(
44+
UrlFinderInterface $urlFinder,
45+
StoreManagerInterface $storeManager,
46+
CustomUrlLocatorInterface $customUrlLocator
47+
) {
48+
$this->urlFinder = $urlFinder;
49+
$this->storeManager = $storeManager;
50+
$this->customUrlLocator = $customUrlLocator;
51+
}
52+
53+
/**
54+
* @inheritdoc
55+
*/
56+
public function resolve(
57+
Field $field,
58+
$context,
59+
ResolveInfo $info,
60+
array $value = null,
61+
array $args = null
62+
) {
63+
if (!isset($args['url']) || empty(trim($args['url']))) {
64+
throw new GraphQlInputException(__('"url" argument should be specified and not empty'));
65+
}
66+
67+
$result = null;
68+
$url = $args['url'];
69+
if (substr($url, 0, 1) === '/' && $url !== '/') {
70+
$url = ltrim($url, '/');
71+
}
72+
$customUrl = $this->customUrlLocator->locateUrl($url);
73+
$url = $customUrl ?: $url;
74+
$urlRewrite = $this->findCanonicalUrl($url);
75+
if ($urlRewrite) {
76+
$result = [
77+
'id' => $urlRewrite->getEntityId(),
78+
'canonical_url' => $urlRewrite->getTargetPath(),
79+
'type' => $this->sanitizeType($urlRewrite->getEntityType())
80+
];
81+
}
82+
return $result;
83+
}
84+
85+
/**
86+
* Find the canonical url passing through all redirects if any
87+
*
88+
* @param string $requestPath
89+
* @return \Magento\UrlRewrite\Service\V1\Data\UrlRewrite|null
90+
*/
91+
private function findCanonicalUrl(string $requestPath) : ?\Magento\UrlRewrite\Service\V1\Data\UrlRewrite
92+
{
93+
$urlRewrite = $this->findUrlFromRequestPath($requestPath);
94+
if ($urlRewrite && $urlRewrite->getRedirectType() > 0) {
95+
while ($urlRewrite && $urlRewrite->getRedirectType() > 0) {
96+
$urlRewrite = $this->findUrlFromRequestPath($urlRewrite->getTargetPath());
97+
}
98+
}
99+
if (!$urlRewrite) {
100+
$urlRewrite = $this->findUrlFromTargetPath($requestPath);
101+
}
102+
103+
return $urlRewrite;
104+
}
105+
106+
/**
107+
* Find a url from a request url on the current store
108+
*
109+
* @param string $requestPath
110+
* @return \Magento\UrlRewrite\Service\V1\Data\UrlRewrite|null
111+
*/
112+
private function findUrlFromRequestPath(string $requestPath) : ?\Magento\UrlRewrite\Service\V1\Data\UrlRewrite
113+
{
114+
return $this->urlFinder->findOneByData(
115+
[
116+
'request_path' => $requestPath,
117+
'store_id' => $this->storeManager->getStore()->getId()
118+
]
119+
);
120+
}
121+
122+
/**
123+
* Find a url from a target url on the current store
124+
*
125+
* @param string $targetPath
126+
* @return \Magento\UrlRewrite\Service\V1\Data\UrlRewrite|null
127+
*/
128+
private function findUrlFromTargetPath(string $targetPath) : ?\Magento\UrlRewrite\Service\V1\Data\UrlRewrite
129+
{
130+
return $this->urlFinder->findOneByData(
131+
[
132+
'target_path' => $targetPath,
133+
'store_id' => $this->storeManager->getStore()->getId()
134+
]
135+
);
136+
}
137+
138+
/**
139+
* Sanitize the type to fit schema specifications
140+
*
141+
* @param string $type
142+
* @return string
143+
*/
144+
private function sanitizeType(string $type) : string
145+
{
146+
return strtoupper(str_replace('-', '_', $type));
147+
}
148+
}

app/code/Magento/UrlRewriteGraphQl/Model/Resolver/UrlRewrite.php

Lines changed: 36 additions & 91 deletions
Original file line numberDiff line numberDiff line change
@@ -11,12 +11,12 @@
1111
use Magento\Framework\GraphQl\Schema\Type\ResolveInfo;
1212
use Magento\Framework\GraphQl\Config\Element\Field;
1313
use Magento\Framework\GraphQl\Query\ResolverInterface;
14-
use Magento\Store\Model\StoreManagerInterface;
14+
use Magento\Framework\Model\AbstractModel;
1515
use Magento\UrlRewrite\Model\UrlFinderInterface;
16-
use Magento\UrlRewriteGraphQl\Model\Resolver\UrlRewrite\CustomUrlLocatorInterface;
16+
use Magento\UrlRewrite\Service\V1\Data\UrlRewrite as UrlRewriteDTO;
1717

1818
/**
19-
* UrlRewrite field resolver, used for GraphQL request processing.
19+
* Returns URL rewrites list for the specified product
2020
*/
2121
class UrlRewrite implements ResolverInterface
2222
{
@@ -25,29 +25,13 @@ class UrlRewrite implements ResolverInterface
2525
*/
2626
private $urlFinder;
2727

28-
/**
29-
* @var StoreManagerInterface
30-
*/
31-
private $storeManager;
32-
33-
/**
34-
* @var CustomUrlLocatorInterface
35-
*/
36-
private $customUrlLocator;
37-
3828
/**
3929
* @param UrlFinderInterface $urlFinder
40-
* @param StoreManagerInterface $storeManager
41-
* @param CustomUrlLocatorInterface $customUrlLocator
4230
*/
4331
public function __construct(
44-
UrlFinderInterface $urlFinder,
45-
StoreManagerInterface $storeManager,
46-
CustomUrlLocatorInterface $customUrlLocator
32+
UrlFinderInterface $urlFinder
4733
) {
4834
$this->urlFinder = $urlFinder;
49-
$this->storeManager = $storeManager;
50-
$this->customUrlLocator = $customUrlLocator;
5135
}
5236

5337
/**
@@ -59,90 +43,51 @@ public function resolve(
5943
ResolveInfo $info,
6044
array $value = null,
6145
array $args = null
62-
) {
63-
if (!isset($args['url']) || empty(trim($args['url']))) {
64-
throw new GraphQlInputException(__('"url" argument should be specified and not empty'));
46+
): array {
47+
if (!isset($value['model'])) {
48+
throw new GraphQlInputException(__('"model" value should be specified'));
6549
}
6650

67-
$result = null;
68-
$url = $args['url'];
69-
if (substr($url, 0, 1) === '/' && $url !== '/') {
70-
$url = ltrim($url, '/');
71-
}
72-
$customUrl = $this->customUrlLocator->locateUrl($url);
73-
$url = $customUrl ?: $url;
74-
$urlRewrite = $this->findCanonicalUrl($url);
75-
if ($urlRewrite) {
76-
$result = [
77-
'id' => $urlRewrite->getEntityId(),
78-
'relative_url' => $urlRewrite->getTargetPath(),
79-
'type' => $this->sanitizeType($urlRewrite->getEntityType())
80-
];
81-
}
82-
return $result;
83-
}
51+
/** @var AbstractModel $entity */
52+
$entity = $value['model'];
53+
$entityId = $entity->getEntityId();
8454

85-
/**
86-
* Find the canonical url passing through all redirects if any
87-
*
88-
* @param string $requestPath
89-
* @return \Magento\UrlRewrite\Service\V1\Data\UrlRewrite|null
90-
*/
91-
private function findCanonicalUrl(string $requestPath) : ?\Magento\UrlRewrite\Service\V1\Data\UrlRewrite
92-
{
93-
$urlRewrite = $this->findUrlFromRequestPath($requestPath);
94-
if ($urlRewrite && $urlRewrite->getRedirectType() > 0) {
95-
while ($urlRewrite && $urlRewrite->getRedirectType() > 0) {
96-
$urlRewrite = $this->findUrlFromRequestPath($urlRewrite->getTargetPath());
55+
$urlRewriteCollection = $this->urlFinder->findAllByData([UrlRewriteDTO::ENTITY_ID => $entityId]);
56+
$urlRewrites = [];
57+
58+
/** @var UrlRewriteDTO $urlRewrite */
59+
foreach ($urlRewriteCollection as $urlRewrite) {
60+
if ($urlRewrite->getRedirectType() !== 0) {
61+
continue;
9762
}
63+
64+
$urlRewrites[] = [
65+
'url' => $urlRewrite->getRequestPath(),
66+
'parameters' => $this->getUrlParameters($urlRewrite->getTargetPath())
67+
];
9868
}
99-
if (!$urlRewrite) {
100-
$urlRewrite = $this->findUrlFromTargetPath($requestPath);
101-
}
102-
103-
return $urlRewrite;
104-
}
10569

106-
/**
107-
* Find a url from a request url on the current store
108-
*
109-
* @param string $requestPath
110-
* @return \Magento\UrlRewrite\Service\V1\Data\UrlRewrite|null
111-
*/
112-
private function findUrlFromRequestPath(string $requestPath) : ?\Magento\UrlRewrite\Service\V1\Data\UrlRewrite
113-
{
114-
return $this->urlFinder->findOneByData(
115-
[
116-
'request_path' => $requestPath,
117-
'store_id' => $this->storeManager->getStore()->getId()
118-
]
119-
);
70+
return $urlRewrites;
12071
}
12172

12273
/**
123-
* Find a url from a target url on the current store
74+
* Parses target path and extracts parameters
12475
*
12576
* @param string $targetPath
126-
* @return \Magento\UrlRewrite\Service\V1\Data\UrlRewrite|null
77+
* @return array
12778
*/
128-
private function findUrlFromTargetPath(string $targetPath) : ?\Magento\UrlRewrite\Service\V1\Data\UrlRewrite
79+
private function getUrlParameters(string $targetPath): array
12980
{
130-
return $this->urlFinder->findOneByData(
131-
[
132-
'target_path' => $targetPath,
133-
'store_id' => $this->storeManager->getStore()->getId()
134-
]
135-
);
136-
}
81+
$urlParameters = [];
82+
$targetPathParts = explode('/', trim($targetPath, '/'));
13783

138-
/**
139-
* Sanitize the type to fit schema specifications
140-
*
141-
* @param string $type
142-
* @return string
143-
*/
144-
private function sanitizeType(string $type) : string
145-
{
146-
return strtoupper(str_replace('-', '_', $type));
84+
for ($i = 3; ($i < sizeof($targetPathParts) - 1); $i += 2) {
85+
$urlParameters[] = [
86+
'name' => $targetPathParts[$i],
87+
'value' => $targetPathParts[$i + 1]
88+
];
89+
}
90+
91+
return $urlParameters;
14792
}
14893
}
Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,25 @@
11
# Copyright © Magento, Inc. All rights reserved.
22
# See COPYING.txt for license details.
33

4-
type EntityUrl @doc(description: "EntityUrl is an output object containing the `id`, `relative_url`, and `type` attributes") {
4+
type EntityUrl @doc(description: "EntityUrl is an output object containing the `id`, `canonical_url`, and `type` attributes") {
55
id: Int @doc(description: "The ID assigned to the object associated with the specified url. This could be a product ID, category ID, or page ID.")
6-
relative_url: String @doc(description: "The internal relative URL. If the specified url is a redirect, the query returns the redirected URL, not the original.")
6+
canonical_url: String @doc(description: "The internal relative URL. If the specified url is a redirect, the query returns the redirected URL, not the original.")
77
type: UrlRewriteEntityTypeEnum @doc(description: "One of PRODUCT, CATEGORY, or CMS_PAGE.")
88
}
99

1010
type Query {
11-
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")
11+
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")
1212
}
1313

1414
enum UrlRewriteEntityTypeEnum {
1515
}
16+
17+
type UrlRewrite @doc(description: "The object contains URL rewrite details") {
18+
url: String @doc(description: "Request URL")
19+
parameters: [HttpQueryParameter] @doc(description: "Request parameters")
20+
}
21+
22+
type HttpQueryParameter @doc(description: "The object details of target path parameters") {
23+
name: String @doc(description: "Parameter name")
24+
value: String @doc(description: "Parameter value")
25+
}

0 commit comments

Comments
 (0)