Skip to content

Commit

Permalink
ENGCOM-3072: Added URL rewrites data to the product interface #107
Browse files Browse the repository at this point in the history
 - 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
  • Loading branch information
magento-engcom-team committed Oct 3, 2018
2 parents da5a9ed + 6d8e43d commit b96a844
Show file tree
Hide file tree
Showing 7 changed files with 370 additions and 112 deletions.
7 changes: 6 additions & 1 deletion app/code/Magento/CatalogUrlRewriteGraphQl/etc/module.xml
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,10 @@
*/
-->
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Module/etc/module.xsd">
<module name="Magento_CatalogUrlRewriteGraphQl" />
<module name="Magento_CatalogUrlRewriteGraphQl" >
<sequence>
<module name="Magento_UrlRewriteGraphQl"/>
<module name="Magento_CatalogGraphQl"/>
</sequence>
</module>
</config>
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down
148 changes: 148 additions & 0 deletions app/code/Magento/UrlRewriteGraphQl/Model/Resolver/EntityUrl.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,148 @@
<?php
/**
* Copyright © Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/
declare(strict_types=1);

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\ResolverInterface;
use Magento\Store\Model\StoreManagerInterface;
use Magento\UrlRewrite\Model\UrlFinderInterface;
use Magento\UrlRewriteGraphQl\Model\Resolver\UrlRewrite\CustomUrlLocatorInterface;

/**
* UrlRewrite field resolver, used for GraphQL request processing.
*/
class EntityUrl implements ResolverInterface
{
/**
* @var UrlFinderInterface
*/
private $urlFinder;

/**
* @var StoreManagerInterface
*/
private $storeManager;

/**
* @var CustomUrlLocatorInterface
*/
private $customUrlLocator;

/**
* @param UrlFinderInterface $urlFinder
* @param StoreManagerInterface $storeManager
* @param CustomUrlLocatorInterface $customUrlLocator
*/
public function __construct(
UrlFinderInterface $urlFinder,
StoreManagerInterface $storeManager,
CustomUrlLocatorInterface $customUrlLocator
) {
$this->urlFinder = $urlFinder;
$this->storeManager = $storeManager;
$this->customUrlLocator = $customUrlLocator;
}

/**
* @inheritdoc
*/
public function resolve(
Field $field,
$context,
ResolveInfo $info,
array $value = null,
array $args = null
) {
if (!isset($args['url']) || empty(trim($args['url']))) {
throw new GraphQlInputException(__('"url" argument should be specified and not empty'));
}

$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 $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));
}
}
127 changes: 36 additions & 91 deletions app/code/Magento/UrlRewriteGraphQl/Model/Resolver/UrlRewrite.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,12 @@
use Magento\Framework\GraphQl\Schema\Type\ResolveInfo;
use Magento\Framework\GraphQl\Config\Element\Field;
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.
* Returns URL rewrites list for the specified product
*/
class UrlRewrite implements ResolverInterface
{
Expand All @@ -25,29 +25,13 @@ class UrlRewrite implements ResolverInterface
*/
private $urlFinder;

/**
* @var StoreManagerInterface
*/
private $storeManager;

/**
* @var CustomUrlLocatorInterface
*/
private $customUrlLocator;

/**
* @param UrlFinderInterface $urlFinder
* @param StoreManagerInterface $storeManager
* @param CustomUrlLocatorInterface $customUrlLocator
*/
public function __construct(
UrlFinderInterface $urlFinder,
StoreManagerInterface $storeManager,
CustomUrlLocatorInterface $customUrlLocator
UrlFinderInterface $urlFinder
) {
$this->urlFinder = $urlFinder;
$this->storeManager = $storeManager;
$this->customUrlLocator = $customUrlLocator;
}

/**
Expand All @@ -59,90 +43,51 @@ public function resolve(
ResolveInfo $info,
array $value = null,
array $args = null
) {
if (!isset($args['url']) || empty(trim($args['url']))) {
throw new GraphQlInputException(__('"url" argument should be specified and not empty'));
): array {
if (!isset($value['model'])) {
throw new GraphQlInputException(__('"model" value should be specified'));
}

$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(),
'relative_url' => $urlRewrite->getTargetPath(),
'type' => $this->sanitizeType($urlRewrite->getEntityType())
];
}
return $result;
}
/** @var AbstractModel $entity */
$entity = $value['model'];
$entityId = $entity->getEntityId();

/**
* 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());
$urlRewriteCollection = $this->urlFinder->findAllByData([UrlRewriteDTO::ENTITY_ID => $entityId]);
$urlRewrites = [];

/** @var UrlRewriteDTO $urlRewrite */
foreach ($urlRewriteCollection 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()
]
);
return $urlRewrites;
}

/**
* 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;
}
}
16 changes: 13 additions & 3 deletions app/code/Magento/UrlRewriteGraphQl/etc/schema.graphqls
Original file line number Diff line number Diff line change
@@ -1,15 +1,25 @@
# Copyright © Magento, Inc. All rights reserved.
# See COPYING.txt for license details.

type EntityUrl @doc(description: "EntityUrl is an output object containing the `id`, `relative_url`, and `type` attributes") {
type EntityUrl @doc(description: "EntityUrl is an output object containing the `id`, `canonical_url`, and `type` attributes") {
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.")
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.")
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.")
type: UrlRewriteEntityTypeEnum @doc(description: "One of PRODUCT, CATEGORY, or CMS_PAGE.")
}

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 relative 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")
}
Loading

0 comments on commit b96a844

Please sign in to comment.