mageplaza / magento-2-blog-graphql

Magento 2 Blog GraphQL is a part of Mageplaza Blog extension that adds GraphQL features, this supports PWA Studio. This upgrade means to give the extension extended scalability to work even more smoothly on your website. Your store will also have a hassle-free and seamless experience with any updates you make in the future thanks to the PWA compatibility.
https://www.mageplaza.com/magento-2-blog-extension/
Other
4 stars 11 forks source link

attributesInstances dependency injection breaks Magento product filtering with GraphQL #2

Open AndyMardell opened 3 years ago

AndyMardell commented 3 years ago

Preconditions

  1. Magento: 2.4.0
  2. PHP: 7.3.22
  3. MySQL: MariaDb:10.4
  4. mageplaza/magento-2-blog-extension: 3.1.3
  5. mageplaza/module-blog-graphql: 1.0.0

Steps to reproduce

  1. Install latest mageplaza/magento-2-blog-extension and mageplaza/module-blog-graphql
  2. Add some example products
  3. Filter regular Magento products with the following GraphQL query:
query {
  products(
    pageSize: 10
    currentPage: 1
    filter:  {
      sku: {
        eq: "24-MB01"
      }
    }
  ) {
    total_count
    items {
      name
    }
  }
}

Expected response

{
  "data": {
    "products": {
      "total_count": 1,
      "items": [
        {
          "name": "Joust Duffle Bag"
        }
      ]
    }
  }
}

Actual response

{
  "errors": [
    {
      "message": "Internal server error",
      "extensions": {
        "category": "internal"
      },
      "locations": [
        {
          "line": 2,
          "column": 3
        }
      ],
      "path": [
        "products"
      ]
    }
  ],
  "data": {
    "products": null
  }
}

Error

The actual error in debug.log is:

main.ERROR: Attribute not found in the visible attributes list {"exception":"[object] (GraphQL\\Error\\Error(code: 0): Attribute not found in the visible attributes list at /var/www/html/vendor/webonyx/graphql-php/src/Error/Error.php:174, LogicException(code: 0): Attribute not found in the visible attributes list at /var/www/html/vendor/magento/framework/GraphQl/Query/Resolver/Argument/AstConverter.php:103)"}

But this (eventually) traces back to Magento/Framework/GraphQl/Query/Resolver/Argument/FieldEntityAttributesPool.php at line 39.

This line should return an array of product attributes in which we can filter by, but instead, the attributesInstances['products'] resolver is overridden by this projects etc/di.xml file on line 42.

This override causes getEntityAttributesForEntityFromField to return:

Array (
   [0] => name
   [1] => products
   [2] => sku
)

When it should return an array similar to:

Array
(
    [name] => Array
        (
            [type] => String
            [fieldName] => name
        )
[...etc]
)

Temporary fix

If someone needs a temporary fix, you can re-override that di by adding

<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd">
<type name="Magento\Framework\GraphQl\Query\Resolver\Argument\FieldEntityAttributesPool">
        <arguments>
            <argument name="attributesInstances" xsi:type="array">
                <item name="products" xsi:type="object">
                    Magento\CatalogGraphQl\Model\Resolver\Products\FilterArgument\ProductEntityAttributesForAst
                </item>
            </argument>
        </arguments>
    </type>
</config>

To your own [Vendor]\[Module]\etc\di.xml file.

Actual fix

I think lines 42-44 of etc/di.xml may have been included by mistake? I'm happy to submit a PR for this but I wanted to check that removing lines 42-44 in etc/di.xml won't cause other issues.

multidimensionro commented 3 years ago

You should update the composer package for this, otherwise the module is useless.

ereztaiar commented 2 years ago

I think there is a better solution for this In the file vendor/mageplaza/module-blog-graphql/Model/Resolver/FilterArgument.php The function getEntityAttributes

public function getEntityAttributes(): array
    {
        $entities = ['Post', 'Topic', 'Category', 'Comment', 'Product'];
        $fields   = [];
        foreach ($entities as $entity) {
            /** @var Field $field */
            foreach ($this->config->getConfigElement($entity)->getFields() as $field) {
                $fields[$field->getName()] = '';
            }
        }

        return array_keys($fields);
    }

Returns the array keys But the function getClausesFromAst of the AstConverter class expects the values Changing the return statement from return array_keys($fields); to return $fields; using a plugin fixed the issue for me for all entity types

ereztaiar commented 2 years ago

I think there is a better solution for this In the file vendor/mageplaza/module-blog-graphql/Model/Resolver/FilterArgument.php The function getEntityAttributes

public function getEntityAttributes(): array
    {
        $entities = ['Post', 'Topic', 'Category', 'Comment', 'Product'];
        $fields   = [];
        foreach ($entities as $entity) {
            /** @var Field $field */
            foreach ($this->config->getConfigElement($entity)->getFields() as $field) {
                $fields[$field->getName()] = '';
            }
        }

        return array_keys($fields);
    }

Returns the array keys But the function getClausesFromAst of the AstConverter class expects the values Changing the return statement from return array_keys($fields); to return $fields; using a plugin fixed the issue for me for all entity types

Seams that this only works for the blog part of the queries When you query products there are issues with the filter and the original fix is required

amitmaurya1024 commented 2 years ago

I think there is a better solution for this In the file vendor/mageplaza/module-blog-graphql/Model/Resolver/FilterArgument.php The function getEntityAttributes

public function getEntityAttributes(): array
    {
        $entities = ['Post', 'Topic', 'Category', 'Comment', 'Product'];
        $fields   = [];
        foreach ($entities as $entity) {
            /** @var Field $field */
            foreach ($this->config->getConfigElement($entity)->getFields() as $field) {
                $fields[$field->getName()] = '';
            }
        }

        return array_keys($fields);
    }

Returns the array keys But the function getClausesFromAst of the AstConverter class expects the values Changing the return statement from return array_keys($fields); to return $fields; using a plugin fixed the issue for me for all entity types

Yes, this works for me. return $fields instead of return array_keys($fields);