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
  • Loading branch information
Valeriy Naida authored Oct 3, 2018
2 parents 0571603 + b96a844 commit f1a2616
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 f1a2616

Please sign in to comment.