Skip to content

Commit

Permalink
Merge remote-tracking branch 'mainline/2.4-develop' into MFTF-3.0.0
Browse files Browse the repository at this point in the history
  • Loading branch information
tomreece committed Mar 11, 2020
2 parents 6a2e0af + dbb7dec commit fe13306
Show file tree
Hide file tree
Showing 25 changed files with 642 additions and 269 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@

<wait stepKey="waitBeforeRunCronIndex" time="30"/>
<magentoCLI stepKey="runCronIndex" command="cron:run --group=index"/>
<wait stepKey="waitAfterRunCronIndex" time="60"/>
</before>
<after>
<!-- Change "Category Products" and "Product Categories" indexers to "Update on Save" mode -->
Expand Down Expand Up @@ -141,6 +142,7 @@
<!-- Run cron -->
<wait stepKey="waitBeforeRunMagentoCron" time="30"/>
<magentoCLI stepKey="runMagentoCron" command="cron:run --group=index"/>
<wait stepKey="waitAfterRunMagentoCron" time="60"/>

<!-- Open categories K, L, M, N on Storefront in order to make sure that new assigments are applied -->
<!-- Category K contains only Products A, C -->
Expand Down Expand Up @@ -202,6 +204,7 @@
<!-- Run Cron once to reindex product changes -->
<wait stepKey="waitBeforeRunCronIndexAfterProductAssignToCategory" time="30"/>
<magentoCLI stepKey="runCronIndexAfterProductAssignToCategory" command="cron:run --group=index"/>
<wait stepKey="waitAfterRunCronIndexAfterProductAssignToCategory" time="60"/>

<!-- Open categories K, L, M, N on Storefront in order to make sure that new assigments are applied -->

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,16 +10,15 @@
use Magento\Framework\Config\ReaderInterface;
use Magento\Framework\GraphQl\Schema\Type\Entity\MapperInterface;
use Magento\Catalog\Model\ResourceModel\Product\Attribute\CollectionFactory;
use Magento\Catalog\Model\ResourceModel\Product\Attribute\Collection;
use Magento\Catalog\Model\ResourceModel\Eav\Attribute;

/**
* Adds custom/eav attributes to product filter type in the GraphQL config.
*
* Product Attribute should satisfy the following criteria:
* - Attribute is searchable
* - "Visible in Advanced Search" is set to "Yes"
* - Attribute of type "Select" must have options
* - (Attribute is searchable AND "Visible in Advanced Search" is set to "Yes")
* - OR attribute is "Used in Layered Navigation"
* - AND Attribute of type "Select" must have options
*/
class FilterAttributeReader implements ReaderInterface
{
Expand Down Expand Up @@ -77,7 +76,7 @@ public function read($scope = null) : array
$typeNames = $this->mapper->getMappedTypes(self::ENTITY_TYPE);
$config = [];

foreach ($this->getAttributeCollection() as $attribute) {
foreach ($this->getFilterAttributes() as $attribute) {
$attributeCode = $attribute->getAttributeCode();

foreach ($typeNames as $typeName) {
Expand Down Expand Up @@ -120,15 +119,25 @@ private function getFilterType(Attribute $attribute): string
}

/**
* Create attribute collection
* Get attributes to use in product filter input
*
* @return Collection|\Magento\Catalog\Model\ResourceModel\Eav\Attribute[]
* @return array
*/
private function getAttributeCollection()
private function getFilterAttributes(): array
{
return $this->collectionFactory->create()
$filterableAttributes = $this->collectionFactory
->create()
->addHasOptionsFilter()
->addIsFilterableFilter()
->getItems();

$searchableAttributes = $this->collectionFactory
->create()
->addHasOptionsFilter()
->addIsSearchableFilter()
->addDisplayInAdvancedSearchFilter();
->addDisplayInAdvancedSearchFilter()
->getItems();

return $filterableAttributes + $searchableAttributes;
}
}
48 changes: 38 additions & 10 deletions app/code/Magento/CatalogGraphQl/Model/Resolver/Category/Image.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@
use Magento\Framework\Exception\LocalizedException;
use Magento\Store\Api\Data\StoreInterface;
use Magento\Framework\Filesystem\DirectoryList;
use Magento\Catalog\Model\Category\FileInfo;
use Magento\Framework\GraphQl\Exception\GraphQlInputException;

/**
* Resolve category image to a fully qualified URL
Expand All @@ -22,12 +24,19 @@ class Image implements ResolverInterface
/** @var DirectoryList */
private $directoryList;

/** @var FileInfo */
private $fileInfo;

/**
* @param DirectoryList $directoryList
* @param FileInfo $fileInfo
*/
public function __construct(DirectoryList $directoryList)
{
public function __construct(
DirectoryList $directoryList,
FileInfo $fileInfo
) {
$this->directoryList = $directoryList;
$this->fileInfo = $fileInfo;
}

/**
Expand All @@ -45,21 +54,40 @@ public function resolve(
}
/** @var \Magento\Catalog\Model\Category $category */
$category = $value['model'];
$imagePath = $category->getImage();
$imagePath = $category->getData('image');
if (empty($imagePath)) {
return null;
}
/** @var StoreInterface $store */
$store = $context->getExtensionAttributes()->getStore();
$baseUrl = $store->getBaseUrl('media');
$baseUrl = $store->getBaseUrl();

$mediaPath = $this->directoryList->getUrlPath('media');
$pos = strpos($imagePath, $mediaPath);
if ($pos !== false) {
$imagePath = substr($imagePath, $pos + strlen($mediaPath), strlen($baseUrl));
$filenameWithMedia = $this->fileInfo->isBeginsWithMediaDirectoryPath($imagePath)
? $imagePath : $this->formatFileNameWithMediaCategoryFolder($imagePath);

if (!$this->fileInfo->isExist($filenameWithMedia)) {
throw new GraphQlInputException(__('Category image not found.'));
}
$imageUrl = rtrim($baseUrl, '/') . '/' . ltrim($imagePath, '/');

return $imageUrl;
// return full url
return rtrim($baseUrl, '/') . $filenameWithMedia;
}

/**
* Format category media folder to filename
*
* @param string $fileName
* @return string
*/
private function formatFileNameWithMediaCategoryFolder(string $fileName): string
{
// phpcs:ignore Magento2.Functions.DiscouragedFunction
$baseFileName = basename($fileName);
return '/'
. $this->directoryList->getUrlPath('media')
. '/'
. ltrim(FileInfo::ENTITY_MEDIA_PATH, '/')
. '/'
. $baseFileName;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,10 @@
*/
class ProductEntityAttributesForAst implements FieldEntityAttributesInterface
{
private const PRODUCT_BASE_TYPE = 'SimpleProduct';

private const PRODUCT_FILTER_INPUT = 'ProductAttributeFilterInput';

/**
* @var ConfigInterface
*/
Expand Down Expand Up @@ -51,9 +55,9 @@ public function __construct(
*/
public function getEntityAttributes() : array
{
$productTypeSchema = $this->config->getConfigElement('SimpleProduct');
$productTypeSchema = $this->config->getConfigElement(self::PRODUCT_BASE_TYPE);
if (!$productTypeSchema instanceof Type) {
throw new \LogicException(__("SimpleProduct type not defined in schema."));
throw new \LogicException(__("%1 type not defined in schema.", self::PRODUCT_BASE_TYPE));
}

$fields = [];
Expand All @@ -69,6 +73,9 @@ public function getEntityAttributes() : array
}
}

$productAttributeFilterFields = $this->getProductAttributeFilterFields();
$fields = array_merge($fields, $productAttributeFilterFields);

foreach ($this->additionalAttributes as $attributeName) {
$fields[$attributeName] = [
'type' => 'String',
Expand All @@ -78,4 +85,24 @@ public function getEntityAttributes() : array

return $fields;
}

/**
* Get fields from ProductAttributeFilterInput
*
* @return array
*/
private function getProductAttributeFilterFields()
{
$filterFields = [];

$productAttributeFilterSchema = $this->config->getConfigElement(self::PRODUCT_FILTER_INPUT);
$productAttributeFilterFields = $productAttributeFilterSchema->getFields();
foreach ($productAttributeFilterFields as $filterField) {
$filterFields[$filterField->getName()] = [
'type' => 'String',
'fieldName' => $filterField->getName(),
];
}
return $filterFields;
}
}
12 changes: 7 additions & 5 deletions app/code/Magento/CatalogGraphQl/etc/schema.graphqls
Original file line number Diff line number Diff line change
Expand Up @@ -199,11 +199,17 @@ type CustomizableFileValue @doc(description: "CustomizableFileValue defines the
interface MediaGalleryInterface @doc(description: "Contains basic information about a product image or video.") @typeResolver(class: "Magento\\CatalogGraphQl\\Model\\MediaGalleryTypeResolver") {
url: String @doc(description: "The URL of the product image or video.") @resolver(class: "Magento\\CatalogGraphQl\\Model\\Resolver\\Product\\MediaGallery\\Url")
label: String @doc(description: "The label of the product image or video.")
position: Int @doc(description: "The media item's position after it has been sorted.")
disabled: Boolean @doc(description: "Whether the image is hidden from view.")
}

type ProductImage implements MediaGalleryInterface @doc(description: "Product image information. Contains the image URL and label.") {
}

type ProductVideo implements MediaGalleryInterface @doc(description: "Contains information about a product video.") {
video_content: ProductMediaGalleryEntriesVideoContent @doc(description: "Contains a ProductMediaGalleryEntriesVideoContent object.")
}

interface CustomizableOptionInterface @typeResolver(class: "Magento\\CatalogGraphQl\\Model\\CustomizableOptionTypeResolver") @doc(description: "The CustomizableOptionInterface contains basic information about a customizable option. It can be implemented by several types of configurable options.") {
title: String @doc(description: "The display name for this option.")
required: Boolean @doc(description: "Indicates whether the option is required.")
Expand Down Expand Up @@ -403,7 +409,7 @@ type MediaGalleryEntry @doc(description: "MediaGalleryEntry defines characterist
media_type: String @doc(description: "image or video.")
label: String @doc(description: "The alt text displayed on the UI when the user points to the image.")
position: Int @doc(description: "The media item's position after it has been sorted.")
disabled: Boolean @doc(description: "Whether the image is hidden from vie.")
disabled: Boolean @doc(description: "Whether the image is hidden from view.")
types: [String] @doc(description: "Array of image types. It can have the following values: image, small_image, thumbnail.")
file: String @doc(description: "The path of the image on the server.")
content: ProductMediaGalleryEntriesContent @doc(description: "Contains a ProductMediaGalleryEntriesContent object.")
Expand Down Expand Up @@ -466,7 +472,3 @@ type StoreConfig @doc(description: "The type contains information about a store
catalog_default_sort_by : String @doc(description: "Default Sort By.")
root_category_id: Int @doc(description: "The ID of the root category") @resolver(class: "Magento\\CatalogGraphQl\\Model\\Resolver\\RootCategoryId")
}

type ProductVideo @doc(description: "Contains information about a product video.") implements MediaGalleryInterface {
video_content: ProductMediaGalleryEntriesVideoContent @doc(description: "Contains a ProductMediaGalleryEntriesVideoContent object.")
}
Original file line number Diff line number Diff line change
Expand Up @@ -134,7 +134,6 @@
<magentoCLI stepKey="removeDownloadableDomain" command="downloadable:domains:remove example.com static.magento.com"/>

<!-- Delete created data -->
<deleteData createDataKey="createCategory" stepKey="deleteCategory"/>
<deleteData createDataKey="createFirstSimpleProduct" stepKey="deleteFisrtSimpleProduct"/>
<deleteData createDataKey="createSecondSimpleProduct" stepKey="deleteSecondSimpleProduct"/>
<deleteData createDataKey="createDownloadableProduct" stepKey="deleteDownloadableProduct"/>
Expand All @@ -147,6 +146,7 @@
<deleteData createDataKey="createConfigurableProduct" stepKey="deleteConfigurableProduct"/>
<deleteData createDataKey="createConfigChildProduct" stepKey="deleteConfigChildProduct"/>
<deleteData createDataKey="createConfigProductAttr" stepKey="deleteConfigProductAttr"/>
<deleteData createDataKey="createCategory" stepKey="deleteCategory"/>
<amOnPage url="{{AdminProductIndexPage.url}}" stepKey="navigateToProductIndex"/>
<actionGroup ref="ResetProductGridToDefaultViewActionGroup" stepKey="resetProductGridColumnsInitial"/>
<!-- Admin logout-->
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
</annotations>

<scrollToTopOfPage stepKey="scrollToTop"/>
<waitForElementVisible selector="{{AdminNewCatalogPriceRule.saveAndApply}}" stepKey="waitForSaveAndApplyButton"/>
<click selector="{{AdminNewCatalogPriceRule.saveAndApply}}" stepKey="saveAndApplyRule"/>
<waitForElementVisible selector="{{AdminMessagesSection.success}}" stepKey="waitForSuccessMessageAppears"/>
<see selector="{{AdminMessagesSection.success}}" userInput="You saved the rule." stepKey="checkSuccessSaveMessage"/>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@

<!-- Save product -->
<actionGroup ref="SaveProductFormActionGroup" stepKey="saveProduct"/>
<magentoCron stepKey="runIndexCronJobs" groups="index"/>

<!-- Assert product in storefront category page -->
<amOnPage url="$$createCategory.name$$.html" stepKey="amOnCategoryPage"/>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,16 +7,14 @@

namespace Magento\QuoteGraphQl\Model\Resolver\ShippingAddress;

use Magento\Directory\Model\Currency;
use Magento\Framework\Api\ExtensibleDataObjectConverter;
use Magento\Framework\Exception\LocalizedException;
use Magento\Framework\Exception\NoSuchEntityException;
use Magento\Framework\GraphQl\Config\Element\Field;
use Magento\Framework\GraphQl\Query\ResolverInterface;
use Magento\Framework\GraphQl\Schema\Type\ResolveInfo;
use Magento\Quote\Api\Data\ShippingMethodInterface;
use Magento\Quote\Model\Cart\ShippingMethodConverter;
use Magento\Store\Api\Data\StoreInterface;
use Magento\Quote\Model\Quote\TotalsCollector;

/**
* @inheritdoc
Expand All @@ -33,16 +31,24 @@ class AvailableShippingMethods implements ResolverInterface
*/
private $shippingMethodConverter;

/**
* @var TotalsCollector
*/
private $totalsCollector;

/**
* @param ExtensibleDataObjectConverter $dataObjectConverter
* @param ShippingMethodConverter $shippingMethodConverter
* @param TotalsCollector $totalsCollector
*/
public function __construct(
ExtensibleDataObjectConverter $dataObjectConverter,
ShippingMethodConverter $shippingMethodConverter
ShippingMethodConverter $shippingMethodConverter,
TotalsCollector $totalsCollector
) {
$this->dataObjectConverter = $dataObjectConverter;
$this->shippingMethodConverter = $shippingMethodConverter;
$this->totalsCollector = $totalsCollector;
}

/**
Expand All @@ -61,9 +67,8 @@ public function resolve(Field $field, $context, ResolveInfo $info, array $value
}

$address->setCollectShippingRates(true);
$address->collectShippingRates();
$cart = $address->getQuote();

$this->totalsCollector->collectAddressTotals($cart, $address);
$methods = [];
$shippingRates = $address->getGroupedAllShippingRates();
foreach ($shippingRates as $carrierRates) {
Expand All @@ -88,7 +93,6 @@ public function resolve(Field $field, $context, ResolveInfo $info, array $value
* @param array $data
* @param string $quoteCurrencyCode
* @return array
* @throws NoSuchEntityException
*/
private function processMoneyTypeData(array $data, string $quoteCurrencyCode): array
{
Expand Down
Loading

0 comments on commit fe13306

Please sign in to comment.