vuestorefront / vue-storefront

Alokai is a Frontend as a Service solution that simplifies composable commerce. It connects all the technologies needed to build and deploy fast & scalable ecommerce frontends. It guides merchants to deliver exceptional customer experiences quickly and easily.
https://www.alokai.com
MIT License
10.64k stars 2.08k forks source link

CMS Block query using the `like` operator returns the wrong result #4735

Closed timdk closed 4 years ago

timdk commented 4 years ago

Current behavior

In short: When querying a CMS Block by its identifier, the query filters are not applied properly. This means the Block component is empty on the storefront.

In detail: When using the default CMS Block component in the default theme to insert a component using its identifier, the createSingleBlockQuery() helper builds a query using the like operator:

https://github.com/DivanteLtd/vue-storefront/blob/master/core/modules/cms/helpers/createSingleBlockQuery.ts#L7

    query = query.applyFilter({ key, value: { like: value } })

This operator is also used when building queries for CMS Pages.

This operator is not handled in the storefront-query-builder package as one of the baseFilters. https://github.com/DivanteLtd/storefront-query-builder/blob/master/src/elasticsearch/body.ts#L75

This means the check inside the inner loop of applyBaseFilters() always fails and the filter is not applied onto bodybuilder queryChain. https://github.com/DivanteLtd/storefront-query-builder/blob/master/src/elasticsearch/body.ts#L216

          if (filterHandler.check({ operator, attribute, value, queryChain })) {
            value = filterHandler.hasOwnProperty('mutator') ? filterHandler.mutator(value) : value
            this.queryChain = filterHandler.filter.call(this, { operator, attribute, value, queryChain })
            return
          }

When the request is made it doesn't have any filters so the response contains all (or top 50) bocks and only the first result is committed into the vuex store by the action. https://github.com/DivanteLtd/vue-storefront/blob/master/core/modules/cms/store/block/actions.ts#L38

        commit(types.CMS_BLOCK_ADD_CMS_BLOCK, blockResponse.items[0])

In my case the first result is the wrong component. Nothing is returned by the state store and on my storefront the component is blank. https://github.com/DivanteLtd/vsf-default/blob/master/components/core/blocks/Cms/Block.vue#L62

        return this.$store.getters[`cmsBlock/getCmsBlockByIdentifier`](this.identifier) // undefined

Expected behavior

I am not sure what the best solution here is but I can see two options

  1. Rewrite any helpers building queries with like to use the eq operator instead
  2. Add a filterHandler for the like operator to the storefront-query-project

I have fixed the issue locally with the first change but maybe the second is a better solution.

Steps to reproduce the issue

It's a little hard to provide a repo because it depends on the data and a full end-to-end magento/VSF configuration.

  1. Set up a Magento2 instance with the CMS API module https://github.com/SnowdogApps/magento2-cms-api
  2. Set up several CMS Blocks in Magento
  3. Import data into elasticsearch using mage2vuestorefront, make sure to include blocks
  4. On any page, using the Block.vue component add your block by its identifier e.g. <Block identifier="footer_col_1" />

NB: If by chance the correct block is returned as the first result of an unfiltered query, it will 'just work' so you may need to experiment with several identifiers to reproduce the issue.

Version of Vue Storefront

Can you handle fixing this bug by yourself?

I can open a PR if a member of the core team identifies solution 1. above as the preferred approach.

Which Release Cycle state this refers to? Info for developer. (doesn't apply to Next)

Pick one option.

Environment details

Additional information

n/a

TTomas commented 4 years ago

I change in my local source core/modules/cms/helpers/createSinglePageLoadQuery.ts Line 7 to // query = query.applyFilter({ key, value: { like: value } }) query = query.applyFilter({ key, value: { eq: value } }) And CMS page work OK in Capybara theme

pkarw commented 4 years ago

@TTomas maybe you could create a PR with this fix? would be great!

timdk commented 4 years ago

@pkarw I can do it, should I target hotfix or master? Edit: I see it's assigned to hotfix 1.12.3

pkarw commented 4 years ago

@timdk please aim at the 1.12.3 thanks!

gibkigonzo commented 4 years ago

It should be handled by this line. https://github.com/DivanteLtd/storefront-query-builder/blob/0ef1f9760eb44edce5b9464a9145ce0a7517a419/src/elasticsearch/body.ts#L224 Please check if you have newest storefront-query-builder @timdk

timdk commented 4 years ago

@gibkigonzo you are right, I set up project after June 10 but my yarn.lock is pulling commit 3984d39 before this line was added. The commit has has since been updated in this repo... just bad timing I guess!

I'll close this PR then! Thanks for your attention