diff --git a/src/_data/toc/graphql.yml b/src/_data/toc/graphql.yml index 3698ef56a79..57e31ddaf1b 100644 --- a/src/_data/toc/graphql.yml +++ b/src/_data/toc/graphql.yml @@ -16,6 +16,9 @@ pages: - label: GraphQL Caching url: /graphql/caching.html + - label: Filtering with custom attributes + url: /graphql/custom-filters.html + - label: Development children: - label: Define the GraphQL schema for a module @@ -50,6 +53,9 @@ pages: - label: category query url: /graphql/queries/category.html + - label: categoryList query + url: /graphql/queries/category-list.html + - label: checkoutAgreements query url: /graphql/queries/checkout-agreements.html @@ -74,6 +80,9 @@ pages: - label: customer query url: /graphql/queries/customer.html + - label: customerCart query + url: /graphql/queries/customer-cart.html + - label: customerDownloadableProducts query url: /graphql/queries/customer-downloadable-products.html @@ -112,9 +121,15 @@ pages: - label: Using mutations url: /graphql/mutations/index.html + - label: addBundleProductsToCart mutation + url: /graphql/mutations/add-bundle-products.html + - label: addConfigurableProductsToCart mutation url: /graphql/mutations/add-configurable-products.html + - label: addDownloadableProductsToCart mutation + url: /graphql/mutations/add-downloadable-products.html + - label: addSimpleProductsToCart mutation url: /graphql/mutations/add-simple-products.html @@ -163,6 +178,9 @@ pages: - label: handlePayflowProResponse mutation url: /graphql/mutations/handle-payflow-pro-response.html + - label: mergeCarts mutation + url: /graphql/mutations/merge-carts.html + - label: placeOrder mutation url: /graphql/mutations/place-order.html diff --git a/src/_data/toc/ui-components-guide.yml b/src/_data/toc/ui-components-guide.yml index 045aeb81925..7cc7f90d45e 100644 --- a/src/_data/toc/ui-components-guide.yml +++ b/src/_data/toc/ui-components-guide.yml @@ -93,6 +93,10 @@ pages: - label: HtmlContent component url: /ui_comp_guide/components/ui-htmlcontent.html + - label: ImagePreview component + include_versions: ["2.3"] + url: /ui_comp_guide/components/ui-image-preview.html + - label: ImageUploader component include_versions: ["2.3"] url: /ui_comp_guide/components/image-uploader/ @@ -113,6 +117,10 @@ pages: - label: Listing (grid) component url: /ui_comp_guide/components/ui-listing-grid.html + - label: Masonry (grid) component + include_versions: ["2.3"] + url: /ui_comp_guide/components/ui-masonry.html + - label: MassActions component url: /ui_comp_guide/components/ui-massactions.html diff --git a/src/_includes/cloud/enable-ssh.md b/src/_includes/cloud/enable-ssh.md index eba0426318c..3225b1ddff0 100644 --- a/src/_includes/cloud/enable-ssh.md +++ b/src/_includes/cloud/enable-ssh.md @@ -51,7 +51,7 @@ To create an SSH key pair: GitHub also uses the key length `-b 4096` in the command. Follow the prompts to complete the key. -1. When prompted to "Enter a file in which to save the key," press **Enter**to save the file to the default location. The prompt displays the location. +1. When prompted to "Enter a file in which to save the key," press **Enter** to save the file to the default location. The prompt displays the location. 1. When prompted to enter a secure passphrase, enter a phrase to use like a password. Make note of this passphrase. You may be requested to enter it depending on tasks you complete using a terminal during development. diff --git a/src/_includes/config/consumers.md b/src/_includes/config/consumers.md new file mode 100644 index 00000000000..a93e7d3e453 --- /dev/null +++ b/src/_includes/config/consumers.md @@ -0,0 +1,7 @@ +Name|Value|Required?| +|`--consumers-wait-for-messages`|Should consumers wait for a message from the queue? 1 - Yes, 0 - No|No| +{:style="table-layout:auto;"} + +`0`—Consumers process available messages in the queue, close the TCP connection, and terminate. Consumers do not wait for additional messages to enter the queue, even if the number of processed messages is less than the `--max_messages` value specified during starting consumers. + +`1`—Consumers continue to process messages from the message queue until reaching the maximum number of messages (the value specified for `--max_messages` on the `queue:consumers:start` command) before closing the TCP connection and terminating the consumer process. If the queue empties before reaching `--max_messages` the consumer waits for more messages to arrive. If you use workers to run consumers instead of using a cron job, set this variable to `1`. diff --git a/src/_includes/graphql/cart-object.md b/src/_includes/graphql/cart-object.md index e40fb0ea36f..d4488eaad8f 100644 --- a/src/_includes/graphql/cart-object.md +++ b/src/_includes/graphql/cart-object.md @@ -1,11 +1,14 @@ Attribute | Data Type | Description --- | --- | --- -`applied_coupon` | [`AppliedCoupon`][AppliedCoupon] | The `AppliedCoupon` object contains the `code` text attribute, which specifies the coupon code +`applied_coupon` | [`AppliedCoupon`][AppliedCoupon] | Deprecated. Use `applied_coupons` instead +`applied_coupons` | [[`AppliedCoupon`]][AppliedCoupon] | An array of `AppliedCoupon` objects. Each object contains the `code` text attribute, which specifies the coupon code `applied_gift_cards` | [[`AppliedGiftCard`]][AppliedGiftCard] | An array of `AppliedGiftCard` objects. An `AppliedGiftCard` object contains the `code` text attribute, which specifies the gift card code. `applied_gift_cards` is a Commerce-only attribute, defined in the GiftCardAccountGraphQl module `applied_store_credit` | [`AppliedStoreCredit`][AppliedStoreCredit] | Contains store credit information applied to the cart. `applied_store_credit` is a Commerce-only attribute, defined in the CustomerBalanceGraphQl module `available_payment_methods` | [[AvailablePaymentMethod]][AvailablePaymentMethod] | Available payment methods -`billing_address` | [BillingCartAddress][BillingCartAddress]! | Contains the billing address specified in the customer's cart +`billing_address` | [BillingCartAddress][BillingCartAddress] | Contains the billing address specified in the customer's cart `email` | String | The customer's email address +`id` | ID! | The ID of the cart +`is_virtual` | Boolean | Indicates whether the cart contains only virtual products `items` | [[CartItemInterface]][CartItemInterface] | Contains the items in the customer's cart `prices` | [CartPrices][CartPrices] | Contains subtotals and totals `selected_payment_method` | [SelectedPaymentMethod][SelectedPaymentMethod] | Selected payment method diff --git a/src/_includes/graphql/cms-block-object.md b/src/_includes/graphql/cms-block-object.md new file mode 100644 index 00000000000..79f0475637f --- /dev/null +++ b/src/_includes/graphql/cms-block-object.md @@ -0,0 +1,7 @@ +The `CmsBlock` object can contain the following attributes: + +Attribute | Data type | Description +--- | --- | --- +`content` | String | The content of the CMS block in raw HTML +`identifier` | String | The CMS block identifier +`title` | String | The title assigned to the CMS block diff --git a/src/_includes/graphql/create-customer.md b/src/_includes/graphql/create-customer.md index c24a21b29cf..f13cae5ebff 100644 --- a/src/_includes/graphql/create-customer.md +++ b/src/_includes/graphql/create-customer.md @@ -1,6 +1,7 @@ Attribute | Data Type | Description --- | --- | --- -`dob` | String | The customer’s date of birth +`date_of_birth` | String | The customer’s date of birth +`dob` | String | Deprecated. Use `date_of_birth` instead. The customer’s date of birth `email` | String | The customer’s email address. Required to create a customer `firstname` | String | The customer’s first name. Required to create a customer `gender` | Int | The customer's gender (Male - 1, Female - 2) diff --git a/src/_includes/graphql/customer-address-input.md b/src/_includes/graphql/customer-address-input.md index cefbe8d9a39..1536fb19ce3 100644 --- a/src/_includes/graphql/customer-address-input.md +++ b/src/_includes/graphql/customer-address-input.md @@ -1,13 +1,14 @@ -### CustomerAddress input {#customerAddressInput} +### CustomerAddressInput attributes {#customerAddressInput} -The `CustomerAddress` input can contain the following attributes: +The `CustomerAddressInput` object can contain the following attributes: Attribute | Data Type | Description --- | --- | --- `city` | String | The city or town `company` | String | The customer's company -`country_id` | String | The customer's country -`custom_attributes` | [CustomerAddressAttribute](#customerAddressAttributeInput) | Address custom attributes +`country_code` | String | The customer's country +`country_id` | String | Deprecated. Use `country_code` instead. The customer's country +`custom_attributes` | [CustomerAddressAttributeInput](#customerAddressAttributeInput) | Deprecated. Not applicable for GraphQL `customer_id` | Int | The customer ID `default_billing` | Boolean | Indicates whether the address is the default billing address `default_shipping` | Boolean | Indicates whether the address is the default shipping address @@ -19,28 +20,28 @@ Attribute | Data Type | Description `middlename` | String | The middle name of the person associated with the shipping/billing address `postcode` | String | The customer's ZIP or postal code `prefix` | String | An honorific, such as Dr., Mr., or Mrs. -`region` | [CustomerAddressRegion](#customerAddressRegionInput) | An object that defines the customer's state or province -`region_id` | Int | A number that uniquely identifies the state, province, or other area +`region` | [CustomerAddressRegionInput](#customerAddressRegionInput) | An object that defines the customer's state or province +`region_id` | Int | Deprecated. Use `region` instead. A number that uniquely identifies the state, province, or other area `street` | [String] | An array of strings that define the street number and name `suffix` | String | A value such as Sr., Jr., or III `telephone` | String | The telephone number `vat_id` | String | The customer's Tax/VAT number (for corporate customers) -### CustomerAddressAttribute input {#customerAddressAttributeInput} +### CustomerAddressAttributeInput attributes {#customerAddressAttributeInput} -The `CustomerAddressAttribute` input can contain the following attributes: +The `CustomerAddressAttributeInput` data type has been deprecated because the contents are not applicable for GraphQL. It can contain the following attributes: Attribute | Data Type | Description --- | --- | --- `attribute_code` | String | Attribute code `value` | String | Attribute value -### CustomerAddressRegion input {#customerAddressRegionInput} +### CustomerAddressRegionInput attributes {#customerAddressRegionInput} -The `customerAddressRegion` input can contain the following attributes: +The `customerAddressRegionInput` object can contain the following attributes: Attribute | Data Type | Description --- | --- | --- -`region_code` | String | The address region code `region` | String | The state or province name -`region_id` | Int | Uniquely identifies the region \ No newline at end of file +`region_code` | String | The address region code +`region_id` | Int | Deprecated. Use `region` instead. Uniquely identifies the region \ No newline at end of file diff --git a/src/_includes/graphql/customer-address-output.md b/src/_includes/graphql/customer-address-output.md index cc96fdc532e..30be8e7ce69 100644 --- a/src/_includes/graphql/customer-address-output.md +++ b/src/_includes/graphql/customer-address-output.md @@ -1,4 +1,4 @@ -### CustomerAddress output {#customerAddressOutput} +### CustomerAddress attributes {#customerAddressOutput} The values assigned to attributes such as `firstname` and `lastname` in this object may be different from those defined in the `Customer` object. @@ -8,8 +8,9 @@ Attribute | Data Type | Description --- | --- | --- `city` | String | The city or town `company` | String | The customer's company -`country_id` | String | The customer's country -`custom_attributes` | [CustomerAddressAttribute](#customerAddressAttributeOutput) | Address custom attributes +`country_code` | CountryCodeEnum | The customer's country +`country_id` | String | Deprecated. Use `country_code` instead. The customer's country +`custom_attributes` | [CustomerAddressAttribute](#customerAddressAttributeOutput) | Deprecated. Not applicable for GraphQL `customer_id` | Int | The customer ID `default_billing` | Boolean | Indicates whether the address is the default billing address `default_shipping` | Boolean | Indicates whether the address is the default shipping address @@ -22,27 +23,27 @@ Attribute | Data Type | Description `postcode` | String | The customer's ZIP or postal code `prefix` | String | An honorific, such as Dr., Mr., or Mrs. `region` | [CustomerAddressRegion](#customerAddressRegionOutput) | An object that defines the customer's state or province -`region_id` | Int | A number that uniquely identifies the state, province, or other area +`region_id` | Int | Deprecated. Use `region` instead. A number that uniquely identifies the state, province, or other area `street` | [String] | An array of strings that define the street number and name `suffix` | String | A value such as Sr., Jr., or III `telephone` | String | The telephone number `vat_id` | String | The customer's Tax/VAT number (for corporate customers) -### CustomerAddressAttribute output {#customerAddressAttributeOutput} +### CustomerAddressAttribute attributes {#customerAddressAttributeOutput} -The `CustomerAddressAttribute` output returns the following attributes: +The `CustomerAddressAttribute` output data type has been deprecated because the contents are not applicable for GraphQL. It can contain the following attributes: Attribute | Data Type | Description --- | --- | --- `attribute_code` | String | Attribute code `value` | String | Attribute value -### CustomerAddressRegion output {#customerAddressRegionOutput} +### CustomerAddressRegion attributes {#customerAddressRegionOutput} The `customerAddressRegion` output returns the following attributes: Attribute | Data Type | Description --- | --- | --- -`region_code` | String | The address region code `region` | String | The state or province name -`region_id` | Int | Uniquely identifies the region \ No newline at end of file +`region_code` | String | The address region code +`region_id` | Int | Deprecated. Use `region` instead. Uniquely identifies the region \ No newline at end of file diff --git a/src/_includes/graphql/customer-input.md b/src/_includes/graphql/customer-input.md index 265b1030ebf..7ce006d1ae2 100644 --- a/src/_includes/graphql/customer-input.md +++ b/src/_includes/graphql/customer-input.md @@ -2,13 +2,14 @@ Attribute | Data Type | Description --- | --- | --- `addresses` | [CustomerAddress](#customerAddressInput) | An array containing the customer's shipping and billing addresses `created_at` | String | Timestamp indicating when the account was created +`date_of_birth` | String | The customer's date of birth `default_billing` | String | The ID assigned to the billing address `default_shipping` | String | The ID assigned to the shipping address -`dob` | String | The customer's date of birth +`dob` | String | Deprecated. Use `date_of_birth` instead. The customer's date of birth `email` | String | The customer's email address `firstname` | String | The customer's first name `gender` | Int | The customer's gender (Male - 1, Female - 2) -`group_id` | Int | The group assigned to the user. Default values are 0 (Not logged in), 1 (General), 2 (Wholesale), and 3 (Retailer) +`group_id` | Int | Deprecated. This attribute is not applicable for GraphQL. The group assigned to the user. Default values are 0 (Not logged in), 1 (General), 2 (Wholesale), and 3 (Retailer) `id` | Int | The ID assigned to the customer `is_subscribed` | Boolean | Indicates whether the customer is subscribed to the company's newsletter `lastname` | String | The customer's family name diff --git a/src/_includes/graphql/customer-output.md b/src/_includes/graphql/customer-output.md index 7b5d6061627..a57805e2244 100644 --- a/src/_includes/graphql/customer-output.md +++ b/src/_includes/graphql/customer-output.md @@ -2,13 +2,14 @@ Attribute | Data Type | Description --- | --- | --- `addresses` | [CustomerAddress](#customerAddressOutput) | An array containing the customer's shipping and billing addresses `created_at` | String | Timestamp indicating when the account was created +`date_of_birth` | String | The customer's date of birth `default_billing` | String | The ID assigned to the billing address `default_shipping` | String | The ID assigned to the shipping address -`dob` | String | The customer's date of birth +`dob` | String | Deprecated. Use `date_of_birth` instead. The customer's date of birth `email` | String | The customer's email address `firstname` | String | The customer's first name `gender` | Int | The customer's gender (Male - 1, Female - 2) -`group_id` | Int | The group assigned to the user. Default values are 0 (Not logged in), 1 (General), 2 (Wholesale), and 3 (Retailer) +`group_id` | Int | Deprecated. This attribute is not applicable for GraphQL. The group assigned to the user. Default values are 0 (Not logged in), 1 (General), 2 (Wholesale), and 3 (Retailer) `id` | Int | The ID assigned to the customer `is_subscribed` | Boolean | Indicates whether the customer is subscribed to the company's newsletter `lastname` | String | The customer's family name @@ -16,5 +17,6 @@ Attribute | Data Type | Description `prefix` | String | An honorific, such as Dr., Mr., or Mrs. `suffix` | String | A value such as Sr., Jr., or III `taxvat` | String | The customer's Tax/VAT number (for corporate customers) +`wishlist` | Wishlist! | Contains the contents of the customer's wish lists {% include graphql/customer-address-output.md %} \ No newline at end of file diff --git a/src/cloud/live/go-live-checklist.md b/src/cloud/live/go-live-checklist.md index 234e95bae41..0b1dc7f33ba 100644 --- a/src/cloud/live/go-live-checklist.md +++ b/src/cloud/live/go-live-checklist.md @@ -91,6 +91,10 @@ You can also test using the following 3rd party options: You can use New Relic services for performance monitoring on Pro and Starter environments. On Pro plan accounts, we provide Adobe-generated alert policies to monitor application and infrastructure performance using New Relic APM and Infrastructure agents. For details on using these services, see [New Relic]({{ site.baseurl }}/cloud/project/new-relic.html). +## Performance monitoring + +You can use New Relic services for performance monitoring on Pro and Starter environments. On Pro plan accounts, we provide Adobe-generated alert policies to monitor application and infrastructure performance using New Relic APM and Infrastructure agents. For details on using these services, see [New Relic]({{ page.baseurl }}/cloud/project/new-relic.html). + {:.ref-header} Next step diff --git a/src/common/images/ui_comps/image-preview-result.png b/src/common/images/ui_comps/image-preview-result.png new file mode 100644 index 00000000000..8ad2d3a5317 Binary files /dev/null and b/src/common/images/ui_comps/image-preview-result.png differ diff --git a/src/common/images/ui_comps/masonry-grid-result.png b/src/common/images/ui_comps/masonry-grid-result.png new file mode 100644 index 00000000000..6e008d63d93 Binary files /dev/null and b/src/common/images/ui_comps/masonry-grid-result.png differ diff --git a/src/guides/v2.2/frontend-dev-guide/layouts/xml-manage.md b/src/guides/v2.2/frontend-dev-guide/layouts/xml-manage.md index 601f48d50f1..10cb49c5a54 100644 --- a/src/guides/v2.2/frontend-dev-guide/layouts/xml-manage.md +++ b/src/guides/v2.2/frontend-dev-guide/layouts/xml-manage.md @@ -549,6 +549,41 @@ As result, the `` tag has a new `my-new-body-class` class on all product p ``` +## Create cms-page/product/category-specific layouts + +As of Magento 2.2.11, merchants can select layout updates to be applied to specific Category/Product/CMS Page pages on the frontend. These layout +updates are made by creating layout XML files following specific naming conventions. + +For Categories: + +- `catalog_category_view_selectable__.xml` + +where: + +- _Category ID_ is the desired category ID. +- _Layout Update Name_ is shown as the option for the __Custom layout update__ field of the __Design__ section on the _Category Edit_ page. + +For Products: + +- `catalog_product_view_selectable__.xml` + +where: + +- _Product SKU_ is the desired product's SKU encoded as a URI. + _example_: "My Product SKU" -> "My%20Product%20SKU" +- _Layout Update Name_ is shown as the option for the __Custom layout update__ field of the __Design__ section on the _Product Edit_ page. + +For CMS Pages: + +- `cms_page_view_selectable__.xml` + +where: + +- _CMS Page Identifier_ is the desired page's _URL Key_ with "/" symbols replaced with "_". +- _Layout Update Name_ is shown as the option for the __Custom layout update__ field of the __Design__ section on _CMS Page Edit_ page. + +These files must be placed in the appropriate folders for layout XML files. They will be available as __Custom Layout Update__ options for Merchants after flushing the cache. + {:.ref-header} Related topics diff --git a/src/guides/v2.2/frontend-dev-guide/templates/template-email.md b/src/guides/v2.2/frontend-dev-guide/templates/template-email.md index bfadc6a86c9..ef2d4a39f9f 100644 --- a/src/guides/v2.2/frontend-dev-guide/templates/template-email.md +++ b/src/guides/v2.2/frontend-dev-guide/templates/template-email.md @@ -64,45 +64,6 @@ To add the store and sales related information to a template, use system variabl System variables are placeholders which are replaced by particular values when the actual email is generated. For example, the Store Hours (`{% raw %}{{config path="general/store_information/hours"}}{% endraw %}`) variable is replaced by the value set in the **STORES** > Settings > **Configuration** > GENERAL > **General** > **Store Information** section. -Here is a list of the most commonly used email template variables that are available: - -* Email Footer Template: `{% raw %}{{template config_path="design/email/footer_template"}}{% endraw %}` -* Email Header Template: `{% raw %}{{template config_path="design/email/header_template"}}{% endraw %}` -* Email Logo Image Alt: `{% raw %}{{var logo_alt}}{% endraw %}` -* Email Logo Image URL: `{% raw %}{{var logo_url}}{% endraw %}` -* Email Logo Image Height: `{% raw %}{{var logo_height}}{% endraw %}` -* Email Logo Image Width: `{% raw %}{{var logo_width}}{% endraw %}` -* Template CSS: `{% raw %}{{var template_styles|raw}}{% endraw %}` -* Base Unsecure URL: `{% raw %}{{config path="web/unsecure/base_url"}}{% endraw %}` -* Base Secure URL: `{% raw %}{{config path="web/secure/base_url"}}{% endraw %}` -* General Contact Name: `{% raw %}{{config path="trans_email/ident_general/name"}}{% endraw %}` -* Sales Representative Contact Name: `{% raw %}{{config path="trans_email/ident_sales/name"}}{% endraw %}` -* Sales Representative Contact Email: `{% raw %}{{config path="trans_email/ident_sales/email"}}{% endraw %}` -* Custom1 Contact Name: `{% raw %}{{config path="trans_email/ident_custom1/name"}}{% endraw %}` -* Custom1 Contact Email: `{% raw %}{{config path="trans_email/ident_custom1/email"}}{% endraw %}` -* Custom2 Contact Name: `{% raw %}{{config path="trans_email/ident_custom2/name"}}{% endraw %}` -* Custom2 Contact Email: `{% raw %}{{config path="trans_email/ident_custom2/email"}}{% endraw %}` -* Store Name: `{% raw %}{{config path="general/store_information/name"}}{% endraw %}` -* Store Phone Number: `{% raw %}{{config path="general/store_information/phone"}}{% endraw %}` -* Store Hours: `{% raw %}{{config path="general/store_information/hours"}}{% endraw %}` -* Country: `{% raw %}{{config path="general/store_information/country_id"}}{% endraw %}` -* Region/State: `{% raw %}{{config path="general/store_information/region_id"}}{% endraw %}` -* Zip/Postal Code: `{% raw %}{{config path="general/store_information/postcode"}}{% endraw %}` -* City: `{% raw %}{{config path="general/store_information/city"}}{% endraw %}` -* Street Address 1: `{% raw %}{{config path="general/store_information/street_line1"}}{% endraw %}` -* Street Address 2: `{% raw %}{{config path="general/store_information/street_line2"}}{% endraw %}` -* Store Contact Address: `{% raw %}{{config path="general/store_information/address"}}{% endraw %}` -* Customer Account URL: `{% raw %}{{var this.getUrl($store, 'customer/account/')}}{% endraw %}` -* Customer Email: `{% raw %}{{var customer.email}}{% endraw %}` -* Customer Name: `{% raw %}{{var customer.name}}{% endraw %}` -* Billing Address: `{% raw %}{{var formattedBillingAddress|raw}}{% endraw %}` -* Email Order Note: `{% raw %}{{var order.getEmailCustomerNote()}}{% endraw %}` -* Order ID: `{% raw %}{{var order.increment_id}}{% endraw %}` -* Order Items Grid: `{% raw %}{{layout handle="sales_email_order_items" order=$order area="frontend"}}{% endraw %}` -* Payment Details: `{% raw %}{{var payment_html|raw}}{% endraw %}` -* Shipping Address: `{% raw %}{{var formattedShippingAddress|raw}}{% endraw %}` -* Shipping Description: `{% raw %}{{var order.getShippingDescription()}}{% endraw %}` - {:.bs-callout-info} You can also create your own custom variables and set their values in the Admin, under **SYSTEM** > **Custom Variables**. @@ -111,7 +72,7 @@ To add a variable to your template content: 1. In the Magento Admin, navigate to **MARKETING** > Communications > **Email Templates** 1. Create a new template or edit an existing template. 1. Click to place the cursor in the text in which to insert the variable. -1. Click **Insert Variable**. A pop-up containing a list of variables opens, including custom variables. The variables in the **Store Contact Information** are available in all email templates whereas the variables in the **Template Variables** section are specific to the template you're editing. The following figure shows an example: +1. Click **Insert Variable**. A pop-up containing a list of variables opens, including custom variables. The variables in the **Store Contact Information** are available in all email templates whereas the variables in the **Template Variables** section are specific to the template you are editing and the extensions you may have installed. The following figure shows an example: ![The list of available variables]({{ site.baseurl }}/common/images/email_insert_variable21.png){:width="70%"}{:height="70%"} diff --git a/src/guides/v2.2/install-gde/install/cli/install-cli-subcommands-lock.md b/src/guides/v2.2/install-gde/install/cli/install-cli-subcommands-lock.md index ede715f6bd5..bb354b1c1b3 100644 --- a/src/guides/v2.2/install-gde/install/cli/install-cli-subcommands-lock.md +++ b/src/guides/v2.2/install-gde/install/cli/install-cli-subcommands-lock.md @@ -18,8 +18,6 @@ Before you run this command, you must do all of the following *or* you must [ins * [Create or update the deployment configuration]({{ page.baseurl }}/install-gde/install/cli/install-cli-subcommands-deployment.html) * [Create the Magento database schema]({{ page.baseurl }}/install-gde/install/cli/install-cli-subcommands-db.html) -{% include install/fully-secure.md %} - ## Configure the lock {#instgde-cli-lockconfig} Configure a lock provider to prevent the launch of duplicate cron jobs and cron groups. (Requires Magento 2.2.5 and later 2.2.x versions or version 2.3.2 and later.) @@ -31,7 +29,7 @@ If you are running Magento Commerce on the cloud infrastructure, you do not need > Command usage ```bash -magento setup:store-config:set [--=, ...] +magento setup:config:set [--=, ...] ``` > Parameter descriptions diff --git a/src/guides/v2.2/ui_comp_guide/concepts/knockout-bindings.md b/src/guides/v2.2/ui_comp_guide/concepts/knockout-bindings.md index 34c512daa22..100c1b9d496 100644 --- a/src/guides/v2.2/ui_comp_guide/concepts/knockout-bindings.md +++ b/src/guides/v2.2/ui_comp_guide/concepts/knockout-bindings.md @@ -346,7 +346,7 @@ Callback that is invoked when user clicks outside of the element. ```html
``` diff --git a/src/guides/v2.3/config-guide/cli/config-cli-subcommands-cache.md b/src/guides/v2.3/config-guide/cli/config-cli-subcommands-cache.md index 892333898a6..e529edba4e2 100644 --- a/src/guides/v2.3/config-guide/cli/config-cli-subcommands-cache.md +++ b/src/guides/v2.3/config-guide/cli/config-cli-subcommands-cache.md @@ -107,6 +107,9 @@ Sample result: {:.bs-callout-info} Enabling a [cache type](https://glossary.magento.com/cache-type) automatically clears that cache type. +{:.bs-callout .bs-callout-info} +As of version 2.3.4, Magento caches all system EAV attributes as they are retrieved. Caching EAV attributes in this manner improves performance, because it decreases the amount of insert/select requests to the DB. However, it increases cache network size as well. Developers can cache custom EAV attributes by running the `bin/magento config:set dev/caching/cache_user_defined_attributes 1` command. This can also be done from the Admin while in Develop mode by setting **Stores** > Settings **Configuration** > **Advanced** > **Developer** > **Caching Settings** > **Cache User Defined Attributes** to **Yes**. + ## Clean and flush cache types {#config-cli-subcommands-cache-clean} To purge out-of-date items from the cache, you can *clean* or *flush* cache types: diff --git a/src/guides/v2.3/config-guide/prod/config-reference-most.md b/src/guides/v2.3/config-guide/prod/config-reference-most.md index 29e59132dfb..46ce14fec03 100644 --- a/src/guides/v2.3/config-guide/prod/config-reference-most.md +++ b/src/guides/v2.3/config-guide/prod/config-reference-most.md @@ -1110,3 +1110,4 @@ Minify CSS Files | `dev/css/minify_files` | | Sign Static Files | `dev/static/sign` | | Asynchronous indexing | `dev/grid/async_indexing` | | +Cache User Defined Attributes | `dev/caching/cache_user_defined_attributes` | | diff --git a/src/guides/v2.3/extension-dev-guide/attributes.md b/src/guides/v2.3/extension-dev-guide/attributes.md index b898593f172..84e7c1e6ab4 100644 --- a/src/guides/v2.3/extension-dev-guide/attributes.md +++ b/src/guides/v2.3/extension-dev-guide/attributes.md @@ -36,6 +36,9 @@ In this case, when `getCustomAttributes()` is called, the system returns only cu The `Customer` module does not treat its EAV attributes in a special manner. As a result, the `getCustomAttributes()` method returns all EAV attributes. +{:.bs-callout .bs-callout-info} +As of version 2.3.4, Magento caches all system EAV attributes as they are retrieved. This behavior is defined in each affected module's `di.xml` file as the `attributesForPreload` argument for ``. Developers can cache custom EAV attributes by running the `bin/magento config:set dev/caching/cache_user_defined_attributes 1` command. This can also be done from the Admin while in Develop mode by setting **Stores** > Settings **Configuration** > **Advanced** > **Developer** > **Caching Settings** > **Cache User Defined Attributes** to **Yes**. Caching EAV attributes while retrieving improves performance as it decreases the amount of insert/select requests to the DB, but it increases the cache network size. + ### Adding Customer EAV attribute for backend only {#customer-eav-attribute} Customer EAV attributes are created using a [data patches]({{ page.baseurl }}/extension-dev-guide/declarative-schema/data-patches.html). diff --git a/src/guides/v2.3/extension-dev-guide/cache/page-caching/private-content.md b/src/guides/v2.3/extension-dev-guide/cache/page-caching/private-content.md index ee095b1bc5f..3bab9d26ecf 100644 --- a/src/guides/v2.3/extension-dev-guide/cache/page-caching/private-content.md +++ b/src/guides/v2.3/extension-dev-guide/cache/page-caching/private-content.md @@ -3,17 +3,17 @@ group: php-developer-guide title: Private content --- -Since private content is specific to individual users, it's reasonable to handle it on the client (i.e., web browser). +Since private content is specific to individual users, it is reasonable to handle it on the client (i.e., web browser). Use our [customer-data]({{ site.mage2bloburl }}/{{ page.guide_version }}/app/code/Magento/Customer/view/frontend/web/js/customer-data.js){:target="_blank"} JS library to store private data in local storage, invalidate private data using customizable rules, and synchronize data with the backend. -This example shows a customer's name on a cacheable page. +This example displays a customer's name on a cacheable page. ## Create a section source {#config-cache-priv-how-source} -The section source class is responsible for retrieving data for the section. As a best practice, we recommend you put your code under the `Vendor/ModuleName/CustomerData` namespace. Your classes must implement the [`Magento\Customer\CustomerData\SectionSourceInterface`]({{ site.mage2bloburl }}/{{ page.guide_version }}/app/code/Magento/Customer/CustomerData/SectionSourceInterface.php){:target="_blank"} interface. +The section source class is responsible for retrieving data for the section. As a best practice, Magento recommends that you put your code within the `Vendor/ModuleName/CustomerData` namespace. Your classes must implement the [`Magento\Customer\CustomerData\SectionSourceInterface`]({{ site.mage2bloburl }}/{{ page.guide_version }}/app/code/Magento/Customer/CustomerData/SectionSourceInterface.php){:target="_blank"} interface. -The public method `getSectionData` must return an array with data for private block. +The public method `getSectionData` must return an array with data for a private block. [Example]({{ site.mage2bloburl }}/{{ page.guide_version }}/app/code/Magento/Catalog/CustomerData/CompareProducts.php#L45-L54){:target="_blank"} @@ -33,8 +33,8 @@ Add the following to your component's [dependency injection](https://glossary.ma To render private content, create a block and a template to display user-agnostic data; this data is replaced with user-specific data by the [UI component](https://glossary.magento.com/ui-component). - {:.bs-callout-info} -Do _not_ use the `$_isScopePrivate` property in your blocks. This property is obsolete and won't work properly. +{:.bs-callout-info} +Do not use the `$_isScopePrivate` property in your blocks. This property is obsolete and will not work properly. Replace private data in blocks with placeholders (using [Knockout](http://knockoutjs.com/documentation/introduction.html){:target="_blank"} syntax). The init scope on the root element is `data-bind="scope: 'compareProducts'"`, where you define the scope name (`compareProducts` in this example) in your [layout](https://glossary.magento.com/layout). @@ -62,7 +62,17 @@ All properties are available in the template. Specify actions that trigger cache invalidation for private content blocks in a `sections.xml` configuration file in the `Vendor/ModuleName/etc/frontend` directory. Magento invalidates the cache on a POST or PUT request. -The following example adds comments to [app/code/Magento/Catalog/etc/frontend/sections.xml]({{ site.mage2bloburl }}/{{ page.guide_version }}/app/code/Magento/Catalog/etc/frontend/sections.xml){:target="_blank"} to show you what the code is doing. +Customer sections was designed to cache private data in browser storage. This means that any customer section will no be updated until proper action was made. + +The are some exception cases: + +- Store and website switching, after any of these action customer section `cart` will be updated. +- Customer cart lifetime option `section_data_lifetime` which is 60 minutes by default. After scheduled time passe section `cart` will be updated. + +{: .bs-callout-info } +Product information will not be simultaneously updated in customer cart (product name, price, product enabled/disabled). Information will be updated after what comes first: `section_data_lifetime` time passed or an action that the update cart triggered. + +The following example adds comments to [app/code/Magento/Catalog/etc/frontend/sections.xml]({{ site.mage2bloburl }}/{{ page.guide_version }}/app/code/Magento/Catalog/etc/frontend/sections.xml){:target="_blank"} so you can see what the code is doing. ```xml @@ -91,12 +101,11 @@ The following example adds comments to [app/code/Magento/Catalog/etc/frontend/se ``` {:.bs-callout-warning} -Use only HTTP POST or PUT methods to change state (e.g., adding to a shopping cart, adding to a wishlist, etc.) and don't expect to see caching on these methods. Using GET or HEAD methods might trigger caching and prevent updates to private content. For more information about caching, see [RFC-2616 section 13](https://www.w3.org/Protocols/rfc2616/rfc2616-sec13.html){:target="_blank"} +Use only HTTP POST or PUT methods to change state (e.g., adding to a shopping cart, adding to a wishlist, etc.) and do not expect to see caching on these methods. Using GET or HEAD methods might trigger caching and prevent updates to private content. For more information about caching, see [RFC-2616 section 13](https://www.w3.org/Protocols/rfc2616/rfc2616-sec13.html){:target="_blank"}. Other examples: - [Checkout]({{ site.mage2bloburl }}/{{ page.guide_version }}/app/code/Magento/Checkout/etc/frontend/sections.xml){:target="_blank"} - - [Customer]({{ site.mage2bloburl }}/{{ page.guide_version }}/app/code/Magento/Customer/etc/frontend/sections.xml){:target="_blank"} ## Version private content {#config-priv-vers} @@ -114,4 +123,7 @@ Versioning works as follows: 1. Any future HTTP POST or PUT request changes the value of `private_content_version` and results in the updated content being cached by the browser. +{:.bs-callout-warning} +The customer data invalidation mechanism no longer relies on the `private_content_version`. + {% include cache/page-cache-checklists.md%} diff --git a/src/guides/v2.3/frontend-dev-guide/layouts/xml-manage.md b/src/guides/v2.3/frontend-dev-guide/layouts/xml-manage.md index 63c2d64bb94..60b97ef705a 100644 --- a/src/guides/v2.3/frontend-dev-guide/layouts/xml-manage.md +++ b/src/guides/v2.3/frontend-dev-guide/layouts/xml-manage.md @@ -575,6 +575,42 @@ You can remove navigation links from the 'My Account' dashboard on the storefron ``` +## Create cms-page/product/category-specific layouts + +As of Magento 2.3.4, merchants can select layout updates to be applied to specific Category/Product/CMS Page pages on the frontend. These layout +updates are made by creating layout XML files following specific naming conventions. + +For Categories: + +- `catalog_category_view_selectable__.xml` + +where: + +- _Category ID_ is desired category ID +- _Layout Update Name_ is what is shown as the option for __Custom layout update__ field of __Design__ section on _Category Edit_ page. + +For Products: + +- `catalog_product_view_selectable__.xml` + +where: + +- _Product SKU_ is the desired product's SKU encoded as a URI. + _example_: "My Product SKU" -> "My%20Product%20SKU" +- _Layout Update Name_ is what is shown as the option for __Custom layout update__ field of __Design__ section on _Product Edit_ page + +For CMS Pages: + +- `cms_page_view_selectable__.xml` + +where: + +- _CMS Page Identifier_ is the desired page's _URL Key_ with "/" symbols replaced with "_" +- _Layout Update Name_ is what is shown as the option for __Custom layout update__ field of __Design__ + section on _CMS Page Edit_ page + +These files must be placed in the appropriate folders for layout XML files. They will be available as __Custom Layout Update__ options for Merchants after flushing the cache. + {:.ref-header} Related topics diff --git a/src/guides/v2.3/frontend-dev-guide/templates/template-email-migration.md b/src/guides/v2.3/frontend-dev-guide/templates/template-email-migration.md new file mode 100644 index 00000000000..732c5927214 --- /dev/null +++ b/src/guides/v2.3/frontend-dev-guide/templates/template-email-migration.md @@ -0,0 +1,231 @@ +--- +group: frontend-developer-guide +title: Migrating custom email templates +functional_areas: + - Frontend +--- + +{% raw %} +With the release of Magento 2.3.4, we made some changes to custom email templates and how they access data and methods for email content. +This topic describes the changes and provides instructions on how to convert your existing custom email templates. + +## Changes to the custom email template workflow + +As of Magento 2.3.4, custom email templates are only allowed to use scalar values for variable data. +Direct calls to methods are no longer allowed. +To be more specific, methods can no longer be called from variables from either the `var` directive or when used as parameters. +For example `{{var order.getEmailCustomerNote()}}` or `{{something myVar=$obj.method()}}` will fail to resolve. + +A 'custom email template' is any new template created in the Magento admin **Marketing** > Communications > **Email Templates** > **Add New Template** area. +Notice in the incorrect example, the `getConfirmationLink()` method is called directly. + +- Old way: `{{var subscriber.getConfirmationLink()}}` +- New way: `{{var subscriber_data.confirmation_link}}` + +We refer to this as 'strict mode' for email templates. +All default templates have been converted to this strict mode. + +{: .bs-callout-info} +All existing custom email templates will continue to work after upgrading to 2.3.4. +Any new email template created after installing 2.3.4 must be written in strict mode. + +## Abstraction example + +Pre-2.3.4, the New Order email template had a line with a direct method call: + +```html +

{{trans "%customer_name," customer_name=$order.getCustomerName()}}

+``` + +As of 2.3.4, with the method call removed: + +```html +

{{trans "%customer_name," customer_name=$order_data.customer_name}}

+``` + +Below, within the `$transport` block, `customer_name` is defined in the `order_data` object and the method call place there. +This `order_data` object is passed to the view page as a `DataObject` and is referenced in the variable as above. + +```php +public function send(Invoice $invoice, $forceSyncMode = false) +{ + $invoice->setSendEmail($this->identityContainer->isEnabled()); + if (!$this->globalConfig->getValue('sales_email/general/async_sending') || $forceSyncMode) { + $order = $invoice->getOrder(); + $this->identityContainer->setStore($order->getStore()); + $transport = [ + 'order' => $order, + 'invoice' => $invoice, + 'comment' => $invoice->getCustomerNoteNotify() ? $invoice->getCustomerNote() : '', + 'billing' => $order->getBillingAddress(), + 'payment_html' => $this->getPaymentHtml($order), + 'store' => $order->getStore(), + 'formattedShippingAddress' => $this->getFormattedShippingAddress($order), + 'formattedBillingAddress' => $this->getFormattedBillingAddress($order), + 'order_data' => [ + 'customer_name' => $order->getCustomerName(), + 'is_not_virtual' => $order->getIsNotVirtual(), + 'email_customer_note' => $order->getEmailCustomerNote(), + 'frontend_status_label' => $order->getFrontendStatusLabel() + ] + ]; + $transportObject = new DataObject($transport); +``` + +In this example, the `customer.name` is being computed within the [model][] file. +Depending on the particular instance of Magento, this data point can be appended within a custom module, directive or any manner of ways. + +## Create a custom directive + +The above examples show changes to default Magento files. We do not recommend editing core files as changes may be lost when upgrading. +Instead, if you need to call a method for a custom email template variable, create a custom directive. +In this example, we will create and pass a `lifetime_spend` custom value. + +1. Create a class that implements `Magento\Framework\Filter\SimpleDirective\ProcessorInterface`: + + ```php + declare(strict_types=1); + namespace GadgetCorp\CustomEmailDirective\Model; + use Magento\Framework\Filter\SimpleDirective\ProcessorInterface; + use Magento\Framework\Pricing\PriceCurrencyInterface; + /** + * Calculates the lifetime spend of all customers + */ + class LifetimeSpendDirective implements ProcessorInterface + { + /** + * @var PriceCurrencyInterface + */ + private $priceCurrency; + /** + * @param PriceCurrencyInterface $priceCurrency + */ + public function __construct(PriceCurrencyInterface $priceCurrency) + { + $this->priceCurrency = $priceCurrency; + } + /** + * @inheritDoc + */ + public function getName(): string + { + return 'lifetime_spend'; + } + /** + * @inheritDoc + */ + public function process($value, array $parameters, ?string $html): string + { + $shouldBold = !empty($parameters['should_bold']); + $amount = $this->priceCurrency->getCurrencySymbol() . $this->calculateLifetimeSpend(); + return ($shouldBold ? '' . $amount . '' : $amount); + } + /** + * @inheritDoc + */ + public function getDefaultFilters(): ?array + { + // Make sure newlines are converted to
tags by default + return ['nl2br']; + } + /** + * Calculate the total amount of money spent by all customers for all time + * + * @return float + */ + private function calculateLifetimeSpend(): float + { + // Add code here to calculate the lifetime spend + return 123.45; + } + } + ``` + + and save the file to //Model. + +1. Add the new directive to the pool by adding this block to `di.xml`. + + ```xml + + + + + GadgetCorp\CustomEmailDirective\Model\LifetimeSpendDirective + + + + + ``` + +The new variable is now available within the email template as `{{lifetime_spend}}`. +Note in the class above, we also defined the parameter `shouldBold`. We can use that with `{{lifetime_spend should_bold=1}}`. +You may also use multiple filters within a var statement: `{{lifetime_spend should_bold=1 |escape|nl2br}}`. + +## Data objects and getUrl + +There are a couple of exceptions to strict mode. + +One exception is for objects that extend from `DataObject`. These can still be called directly. +Even then, we do not actually call the getter method directly, but rather, resolve which key is needed and call `getData()` instead. + +For example, if we have: + +```php +$template->setVariables(['customer_data'=>new DataObject('my_key' => 'foo')]); +``` + +and in the template where we have + +```php +{{somedir mydir mydir=$customer_data.getMyKey()}} +``` + +the directive will resolve to “foo”. + +The same is true for `{{directive foo foo=$customer_data.my_key()}}`. +But note that in both cases the DataObject will not have `getMyKey` invoked but rather `getData(‘my_key’)` is invoked instead. + +The second exception is for `getUrl`. +Directives that use the format `{{var this.getUrl(params)}}` will still continue to work for now. + +## Advanced filtering + +As part of this change, we have removed the limit of processing 2 filters per directive. +Now `{{var order_data.shipping_description|filter1|filter2|filter3}}` will work. + +## Nested arrays + +Getting data from nested arrays is now supported. +For example, if we have: + +```php +$template->setVariables(['customer_data'=> ['name' => ['first_name' => 'John']]]); +``` +and in the template: + +```php +{{mydir test fname=$customer_data.name.first_name}} +``` +it will resolve to “John”. + +This new syntax also works in combination with the `DataObject` exception. +For example, if we have: + +```php +$template->setVariables(['customer_data'=> ['name' => new DataObject('first_name' => 'John')]]); +``` +and in the template we have: + +```php +{{mydir dir fname=$customer_data.name.first_name}} +``` + +it will resolve to “John”. + +{% endraw %} + + +[Insert Variable]: https://devdocs.magento.com/guides/v2.3/frontend-dev-guide/templates/template-email.html#customize-content +[New Order email template]: https://github.com/magento/magento2/blob/2.3-develop/app/code/Magento/Sales/view/frontend/email/order_new.html +[model]: https://github.com/magento/magento2ce/blob/2.3-develop/app/code/Magento/Sales/Model/Order/Email/Sender/InvoiceSender.php +[1]: https://github.com/magento/magento2ce/blob/2.3-develop/app/code/Magento/Email/Model/AbstractTemplate.php diff --git a/src/guides/v2.3/frontend-dev-guide/templates/template-email.md b/src/guides/v2.3/frontend-dev-guide/templates/template-email.md index bfadc6a86c9..5e2d55dd181 100644 --- a/src/guides/v2.3/frontend-dev-guide/templates/template-email.md +++ b/src/guides/v2.3/frontend-dev-guide/templates/template-email.md @@ -5,6 +5,10 @@ functional_areas: - Frontend --- +{:.bs-callout-warning} +Magento 2.3.4 restricts the way that custom variables can be used within email templates. +See [Migrating custom email templates](template-email-migration.html) for more information. + ## Customize email templates {#customize-email-templates} Email templates are stored in the `/view//email` directory of their respective modules. For example, the template for the new order transactional email for the Sales module is located in [`/view/frontend/email/order_new.html`]({{ site.mage2bloburl }}/{{ page.guide_version }}/app/code/Magento/Sales/view/frontend/email/order_new.html). @@ -60,49 +64,14 @@ You can customize header and footer templates using either the [theme](#customiz ### Customize email content {#customize-content} +{:.bs-callout-warning} +Custom variables used within email templates in Magento 2.3.4+ must be written in 'strict mode'. +See [Migrating custom email templates](template-email-migration.html) for more information. + To add the store and sales related information to a template, use system variables. System variables are placeholders which are replaced by particular values when the actual email is generated. For example, the Store Hours (`{% raw %}{{config path="general/store_information/hours"}}{% endraw %}`) variable is replaced by the value set in the **STORES** > Settings > **Configuration** > GENERAL > **General** > **Store Information** section. -Here is a list of the most commonly used email template variables that are available: - -* Email Footer Template: `{% raw %}{{template config_path="design/email/footer_template"}}{% endraw %}` -* Email Header Template: `{% raw %}{{template config_path="design/email/header_template"}}{% endraw %}` -* Email Logo Image Alt: `{% raw %}{{var logo_alt}}{% endraw %}` -* Email Logo Image URL: `{% raw %}{{var logo_url}}{% endraw %}` -* Email Logo Image Height: `{% raw %}{{var logo_height}}{% endraw %}` -* Email Logo Image Width: `{% raw %}{{var logo_width}}{% endraw %}` -* Template CSS: `{% raw %}{{var template_styles|raw}}{% endraw %}` -* Base Unsecure URL: `{% raw %}{{config path="web/unsecure/base_url"}}{% endraw %}` -* Base Secure URL: `{% raw %}{{config path="web/secure/base_url"}}{% endraw %}` -* General Contact Name: `{% raw %}{{config path="trans_email/ident_general/name"}}{% endraw %}` -* Sales Representative Contact Name: `{% raw %}{{config path="trans_email/ident_sales/name"}}{% endraw %}` -* Sales Representative Contact Email: `{% raw %}{{config path="trans_email/ident_sales/email"}}{% endraw %}` -* Custom1 Contact Name: `{% raw %}{{config path="trans_email/ident_custom1/name"}}{% endraw %}` -* Custom1 Contact Email: `{% raw %}{{config path="trans_email/ident_custom1/email"}}{% endraw %}` -* Custom2 Contact Name: `{% raw %}{{config path="trans_email/ident_custom2/name"}}{% endraw %}` -* Custom2 Contact Email: `{% raw %}{{config path="trans_email/ident_custom2/email"}}{% endraw %}` -* Store Name: `{% raw %}{{config path="general/store_information/name"}}{% endraw %}` -* Store Phone Number: `{% raw %}{{config path="general/store_information/phone"}}{% endraw %}` -* Store Hours: `{% raw %}{{config path="general/store_information/hours"}}{% endraw %}` -* Country: `{% raw %}{{config path="general/store_information/country_id"}}{% endraw %}` -* Region/State: `{% raw %}{{config path="general/store_information/region_id"}}{% endraw %}` -* Zip/Postal Code: `{% raw %}{{config path="general/store_information/postcode"}}{% endraw %}` -* City: `{% raw %}{{config path="general/store_information/city"}}{% endraw %}` -* Street Address 1: `{% raw %}{{config path="general/store_information/street_line1"}}{% endraw %}` -* Street Address 2: `{% raw %}{{config path="general/store_information/street_line2"}}{% endraw %}` -* Store Contact Address: `{% raw %}{{config path="general/store_information/address"}}{% endraw %}` -* Customer Account URL: `{% raw %}{{var this.getUrl($store, 'customer/account/')}}{% endraw %}` -* Customer Email: `{% raw %}{{var customer.email}}{% endraw %}` -* Customer Name: `{% raw %}{{var customer.name}}{% endraw %}` -* Billing Address: `{% raw %}{{var formattedBillingAddress|raw}}{% endraw %}` -* Email Order Note: `{% raw %}{{var order.getEmailCustomerNote()}}{% endraw %}` -* Order ID: `{% raw %}{{var order.increment_id}}{% endraw %}` -* Order Items Grid: `{% raw %}{{layout handle="sales_email_order_items" order=$order area="frontend"}}{% endraw %}` -* Payment Details: `{% raw %}{{var payment_html|raw}}{% endraw %}` -* Shipping Address: `{% raw %}{{var formattedShippingAddress|raw}}{% endraw %}` -* Shipping Description: `{% raw %}{{var order.getShippingDescription()}}{% endraw %}` - {:.bs-callout-info} You can also create your own custom variables and set their values in the Admin, under **SYSTEM** > **Custom Variables**. @@ -111,7 +80,7 @@ To add a variable to your template content: 1. In the Magento Admin, navigate to **MARKETING** > Communications > **Email Templates** 1. Create a new template or edit an existing template. 1. Click to place the cursor in the text in which to insert the variable. -1. Click **Insert Variable**. A pop-up containing a list of variables opens, including custom variables. The variables in the **Store Contact Information** are available in all email templates whereas the variables in the **Template Variables** section are specific to the template you're editing. The following figure shows an example: +1. Click **Insert Variable**. A pop-up containing a list of variables opens, including custom variables. The variables in the **Store Contact Information** are available in all email templates whereas the variables in the **Template Variables** section are specific to the template you are editing and the extensions you may have installed. The following figure shows an example: ![The list of available variables]({{ site.baseurl }}/common/images/email_insert_variable21.png){:width="70%"}{:height="70%"} @@ -402,7 +371,9 @@ The `trans` directive will translate strings into whatever locale is configured The directive supports multiple named parameters, separated by spaces. For example: ```html -{% raw %}{{trans "Dear %first_name %last_name," first_name=$first_name last_name=$last_name}}{% endraw %} +{% raw %} +{{trans "Dear %first_name %last_name," first_name=$first_name last_name=$last_name}} +{% endraw %} ``` Please note, that variable assignment must not contain spaces. @@ -410,47 +381,26 @@ Please note, that variable assignment must not contain spaces. Correct: ```html -{% raw %}{{trans "Thank you for your order from %store_name." store_name=$store.getFrontendName()}}{% endraw %} +{% raw %} +{{trans "Thank you for your order from %store_name." store_name=$store.getFrontendName()}} +{% endraw %} ``` Incorrect: ```html -{% raw %}{{trans "Thank you for your order from %store_name." store_name = $store.getFrontendName()}}{% endraw %} +{% raw %} +{{trans "Thank you for your order from %store_name." store_name = $store.getFrontendName()}} +{% endraw %} ``` -{:.bs-callout-info} +{:.bs-callout .bs-callout-info} Exception: argument value can contain spaces if it is enclosed in brackets. ## Supported email clients and devices {#supported-clients} -We tested responsive emails using a combination of real devices and [Litmus](http://litmus.com/). Due to the greatly varied level of support among email clients for modern web technologies, not all email clients rendered the emails perfectly. However, all of the following clients should render the emails in a manner that allows them to be easily read without obvious issues. - -* Supported Desktop Clients - * Apple Mail 7 (OS X 10.9) - * Apple Mail 8 (OS X 10.10) - * Outlook 2003 (Windows 7) - * Outlook 2007 (Windows 7) - * Outlook 2010 (Windows 7) - * Outlook 2013 (Windows 7) - * Outlook 2016 (OS X 10.10) -* Supported Mobile Clients - * Native email app (Android 2.3) - * Native email app (Android 4.2) - * Gmail app (Android 4.2) - * Native email app (Blackberry 5 OS) - * iOS 7 (iPhone 5s) - * iOS 8 (iPad Retina) - * iOS 8 (iPad Mini) - * iOS 8 (iPhone 6) - * iOS 8 (iPhone 6 Plus) - * Windows Phone 8 -* Supported Web Clients (tested in combination of Firefox, Chrome, and Internet Explorer) - * AOL Mail - * Gmail - * Office 365 - * Outlook.com - * Yahoo! Mail +We test responsive emails using a combination of real devices and [Litmus](http://litmus.com/). Due to the greatly varied level of support among email clients for modern web technologies, not all email clients rendered the emails perfectly. +We strive to support all current, modern e-mail clients. Let us know about any client-specific issues you might have. ## Newsletter templates {#newsletter-templates} diff --git a/src/guides/v2.3/graphql/caching.md b/src/guides/v2.3/graphql/caching.md index 7564e13348e..9106fee0b2c 100644 --- a/src/guides/v2.3/graphql/caching.md +++ b/src/guides/v2.3/graphql/caching.md @@ -11,7 +11,8 @@ The definitions for some queries include cache tags. Full page caching uses thes Magento caches the following queries: -* `category` +* `category` (deprecated) +* `categoryList` * `cmsBlocks` * `cmsPage` * `products` diff --git a/src/guides/v2.3/graphql/custom-filters.md b/src/guides/v2.3/graphql/custom-filters.md new file mode 100644 index 00000000000..636a00afb9c --- /dev/null +++ b/src/guides/v2.3/graphql/custom-filters.md @@ -0,0 +1,88 @@ +--- +group: graphql +title: Filtering with custom attributes +--- + +As of Magento 2.3.4, the `filter` attribute of the [`products`]({{page.baseurl}}/graphql/queries/products.html) query accepts the `ProductAttributeFilterInput` object. (In previous versions, the `filter` attribute required a `ProductFilterInput` object. This object contained a hard-coded list of filterable attributes, and you could not filter on a custom attribute or any other attribute that was not on the list.) + +## Prerequisites + +To enable a custom attribute (or any attribute that is not listed by default in the `ProductAttributeFilterInput` object) for filtering, select the attribute on the **Stores** > Attributes > **Product** page in the Admin and edit the following fields: + +Field | Setting +--- | --- +**Use in Search** | Yes +**Visible in Advanced Search** | Yes +**Use in Layered Navigation** | Filterable (with results) or Filterable (no results) +**Use in Search Results Layered Navigation** | Yes + +## Define the filter for your query + +The [`filter`]({{page.baseurl}}/graphql/queries/products.html#ProductFilterInput) definition for your custom attribute requires one of the following input data types: + +- `FilterEqualTypeInput` - Specify this data type when the **Catalog Input Type for Store Owner** field for your custom attribute is set to Yes/No, Select, or Multiple select. Your filter can contain the `eq` or `in` attribute. Use the `eq` attribute to exactly match the specified string. Use the `in` attribute to filter on a comma-separated list of values. +- `FilterMatchTypeInput` - Specify this data type when the the **Catalog Input Type for Store Owner** field for your custom attribute is set to Text Field or Text Area. Your filter must contain the `match` attribute, which will return all items that exactly match the specified string. +- `FilterRangeTypeInput` - Specify this data type when the the **Catalog Input Type for Store Owner** field for your custom attribute is set to Price or Date. Your filter can contain one or both of the `to` and `from` attributes, which serve to provide a range of values to filter on. + +## Example + +In this example, the custom attribute `volume` was assigned to the `bags` attribute group. Running the [`customAttributeMetadata` query]({{page.baseurl}}/graphql/queries/custom-attribute-metadata.html) on this custom attribute reveals that the `label` and `value` values for the attribute's options are as follows: + +`label` | `value` +--- | --- +`Large` | `216` +`Medium` | `217` +`Small` | `218` + +In this scenario, a `products` search filtered to return items where the `volume` attribute is set to `Large` would be similar to the following: + +**Request:** + +```graphql +{ + products(filter: { volume: { eq: "216" } }) { + total_count + items { + name + sku + } + } +} +``` + +**Response:** + +The response might be similar to the following: + +```json +{ + "data": { + "products": { + "total_count": 1, + "items": [ + { + "name": "Wayfarer Messenger Bag", + "sku": "24-MB05" + } + ] + } + } +} +``` + +## Output attributes + +When a product requires a filter attribute that is not a field on its output schema, inject the attribute name into the class in a module's `di.xml` file. + +```xml + + + + field + other_field + + + +``` + +This example adds `field_to_sort` and `other_field_to_sort` attributes to the `additionalAttributes` array defined in the `ProductEntityAttributesForAst` class. The array already contains the `min_price`, `max_price`, and `category_ids` attributes. diff --git a/src/guides/v2.3/graphql/develop/create-graphqls-file.md b/src/guides/v2.3/graphql/develop/create-graphqls-file.md index 23262ff5843..571cd00b9b3 100644 --- a/src/guides/v2.3/graphql/develop/create-graphqls-file.md +++ b/src/guides/v2.3/graphql/develop/create-graphqls-file.md @@ -22,16 +22,16 @@ The base `schema.graphqls` file, located in the `app/code/Magento/GraphQl/etc/` A query definition can be one line, or it can be complex. If your module's query implements `searchCriteria`, then you must define arguments that define filters and pagination information, all of which adds complexity. However, if you expect a single result from your query, then its definition can be simple. -The following example shows the `products` query. The `type` is defined as a `Query`. The `products` definitions define the keywords that are used to construct a query, as shown in [Queries]({{ page.baseurl }}/graphql/queries/index.html). The parameter definitions will be discussed in [Specify output attributes](#specify-output-attributes). +The following example shows the `products` query. The `type` is defined as a `Query`. The `products` definitions define the keywords that are used to construct a query, as shown in [Using queries]({{ page.baseurl }}/graphql/queries/index.html). The parameter definitions will be discussed in [Specify output attributes](#specify-output-attributes). ```text type Query { products ( - search: String, - filter: ProductFilterInput, - pageSize: Int = 20, - currentPage: Int = 1, - sort: ProductSortInput + search: String + filter: ProductAttributeFilterInput + pageSize: Int = 20 + currentPage: Int = 1 + sort: ProductAttributeSortInput ): Products @resolver(class: "Magento\\CatalogGraphQl\\Model\\Resolver\\Products") } ``` @@ -101,11 +101,7 @@ url_key: String @doc(description: "The url key assigned to the product") product_count: Int @doc(description: "The number of products") ``` -Use the `@deprecated` directive to mark a query, mutation, or attribute as deprecated: - -```text -@deprecated(reason: "description") -``` +Use the `@deprecated` directive to deprecate attributes and enum values. The GraphQL specification does not permit deprecating input values or arguments. The `reason` keyword allows you to specify which attribute/field or enum value should be used instead. For example: diff --git a/src/guides/v2.3/graphql/develop/identity-class.md b/src/guides/v2.3/graphql/develop/identity-class.md index dd923f09724..5d4ede6bf6a 100644 --- a/src/guides/v2.3/graphql/develop/identity-class.md +++ b/src/guides/v2.3/graphql/develop/identity-class.md @@ -9,7 +9,7 @@ An Identity class implements `Magento\Framework\GraphQl\Query\Resolver\IdentityI * Choose a cache tag prefix for the entity. -* Your implementation of the `getIdentities(array $resolvedData)` method. The method maps the array of enties data to an array of cache tags, one for each entity. Generally, this method takes an array of query results and creates a cache tag for each entity based on the original string and the unique identifier for each item to be cached. For example, the getIdentities method for the `CatalogGraphQl` component appends the product ID to the `cat_p` cache tag prefix, such as `cat_p_1`, `cat_p_2`, and so on. Usually the method also adds the cache tag without an appended ID to the result array, so all cache records can be removed at once, and not only cache records for specific entities. +* Your implementation of the `getIdentities(array $resolvedData)` method. The method maps the array of entities data to an array of cache tags, one for each entity. Generally, this method takes an array of query results and creates a cache tag for each entity based on the original string and the unique identifier for each item to be cached. For example, the `getIdentities` method for the `CatalogGraphQl` component appends the product ID to the `cat_p` cache tag prefix, such as `cat_p_1`, `cat_p_2`, and so on. Usually the method also adds the cache tag without an appended ID to the result array, so all cache records can be removed at once, and not only cache records for specific entities. Use following example as the basis for your custom `Identity` class: diff --git a/src/guides/v2.3/graphql/develop/resolvers.md b/src/guides/v2.3/graphql/develop/resolvers.md index f83b0739719..dc6b457387f 100644 --- a/src/guides/v2.3/graphql/develop/resolvers.md +++ b/src/guides/v2.3/graphql/develop/resolvers.md @@ -5,34 +5,7 @@ title: Resolvers A resolver performs GraphQL request processing. In general, it is responsible for constructing a query, fetching data and performing any calculations, then transforming the fetched and calculated data into a GraphQL array format. Finally, it returns the results wrapped by a callable function. -A resolver requires the following arguments: - -- $field -- $context -- $info -- $value -- $args - -```php - /** - * Fetches the data from persistence models and format it according to the GraphQL schema. - * - * @param \Magento\Framework\GraphQl\Config\Element\Field $field - * @param ContextInterface $context - * @param ResolveInfo $info - * @param array|null $value - * @param array|null $args - * @throws \Exception - * @return mixed|Value - */ - public function resolve( - Field $field, - $context, - ResolveInfo $info, - array $value = null, - array $args = null - ); -``` +A GraphQL request is represented by the following arguments, which will be processed by a resolver: Field | Type | Description --- | --- | --- @@ -42,7 +15,185 @@ $info | [`Magento\Framework\GraphQl\Schema\Type\ResolveInfo`]({{ site.mage2blobu $value | array | Contains additional query parameters. `Null` in most cases. $args | array | Contains input arguments of query. -A GraphQL resolver must implement the [`\Magento\Framework\GraphQl\Query\ResolverInterface`]({{ site.mage2bloburl }}/{{ page.guide_version }}/lib/internal/Magento/Framework/GraphQl/Query/ResolverInterface.php) interface. This interface returns [`\Magento\Framework\GraphQl\Query\Resolver\Value`]({{ site.mage2bloburl }}/{{ page.guide_version }}/lib/internal/Magento/Framework/GraphQl/Query/Resolver/Value.php) or any type of data (mixed). This value takes in a callable function to its constructor that will be invoked at the latest possible time for the resolver to require its data. As a result, a list of items being resolved can be retrieved all at once by establishing a buffer that contains all relevant parent data to filter and fetch for the children list data. +A GraphQL resolver must implement one of the following interfaces: + +- [`\Magento\Framework\GraphQl\Query\Resolver\BatchResolverInterface`]({{ site.mage2bloburl }}/{{ page.guide_version }}/lib/internal/Magento/Framework/GraphQl/Query/Resolver/BatchResolverInterface.php) + +- [`\Magento\Framework\GraphQl\Query\Resolver\BatchServiceContractResolverInterface`]({{ site.mage2bloburl }}/{{ page.guide_version }}/lib/internal/Magento/Framework/GraphQl/Query/Resolver/BatchServiceContractResolverInterface.php) + +- [`\Magento\Framework\GraphQl\Query\ResolverInterface`]({{ site.mage2bloburl }}/{{ page.guide_version }}/lib/internal/Magento/Framework/GraphQl/Query/ResolverInterface.php) + +The first two interfaces provide a way to resolve multiple branches/leaves at once (known as batching), while the last one resolves one request at a time. Magento recommends using batch resolvers for queries because they improve performance by fetching information required to resolve multiple GraphQL requests with a single operation. + +## Query resolvers + +### BatchResolverInterface + +Batch resolvers gather GraphQL requests for the same field until there is no way to process the tree further without resolving previous requests. + +Consider the following example: + +```graphql +query ($filter: ProductAttributeFilterInput!) { + products (filter: $filter) { + items { + id + sku + related_products { + sku + related_products { + sku + } + } + } + total_count + } +} +``` + +The query loads a list of products, the SKUs of their related products, and then any secondary related product SKUs. + +Loading a list of related products individually for each product would be expensive performance-wise. With batch resolvers, you can load linked products for all products that were initially found, then group them by root products. After the `items` branch is resolved, a batch resolver for `related_products` will be called for the first product found. Instead of resolving the list right away, it will just add the first product to the list of products that require loading additional related products. After all the products from the `items` branch have been loaded, the lists of related products must be loaded. Then, `BatchResolverInterface::resolve()` executes with a gathered list of previous requests to `related_products` branches. At this point, the resolver is able to extract product DTOs from each GraphQL request, load all the product links, sort them by root products, and generate GraphQL values for each branch. After this is done, the same batching will take place when resolving child `related_products` branches. + +The following pseudo-code shows a `related_products` branch resolver: + +```php +class RelatedProducts implements BatchResolverInterface +{ + ... + + public function resolve(ContextInterface $context, Field $field, array $requests): BatchResponse + { + //Get the list of products we need to load related products for + $rootProductIds = array_map(function ($request) { return $request->getValue()['model']->getId(); }, $requests); + + //Load the links + $productLinks = $this->service->getRelatedProductLinks($rootProductIds); + + //Sort the links + $response = new BatchResponse(); + foreach ($requests as $request) { + $response->addResponse($request, $productLinks[$request->getValue()['model']->getId()]); + } + + return $response; + } +} +``` + +Each GraphQL request object must be assigned a [`\Magento\Framework\GraphQl\Query\Resolver\Value`]({{ site.mage2bloburl }}/{{ page.guide_version }}/lib/internal/Magento/Framework/GraphQl/Query/Resolver/Value.php) result type or any type of data (mixed). This value takes in a callable function to its constructor that will be invoked at the latest possible time for the resolver to acquire its data. As a result, a list of items being resolved can be retrieved all at once by establishing a buffer that contains all relevant parent data to filter and fetch for the children list data. + +[`\Magento\RelatedProductGraphQl\Model\Resolver\Batch\AbstractLinkedProducts`]({{ site.mage2bloburl }}/{{ page.guide_version }}/app/code/Magento/RelatedProductGraphQl/Model/Resolver/Batch/AbstractLikedProducts.php) contains an example of batch resolver implementation. + +### BatchServiceContractResolverInterface + +Requests for this interface to resolve are gathered into batches in the same way as for `BatchResolverInterface`, except that the actual resolving is delegated to a batch service contract. The job of the `BatchServiceContractResolverInterface` resolver is to convert GraphQL requests into DTOs acceptable by the service contract, and then convert results returned by the contract into a GraphQL response. + +Consider the same example query: + +```graphql +query ($filter: ProductAttributeFilterInput!) { + products (filter: $filter) { + items { + id + sku + related_products { + sku + related_products { + sku + } + } + } + total_count + } +} +``` + +Here, we will delegate loading all related products to a service that accepts a list of root product IDs, and then returns individual lists for each. + +Pseudo-code for a GraphQL resolver delegating the work to a service contract may look like this: + +```php +class RelatedProductsResolver implements BatchServiceContractResolverInterface +{ + ... + + public function getServiceContract(): array + { + return [ProductLinksRetriever::class, 'getRelatedProducts']; + } + + public function convertToServiceArgument(ResolveRequestInterface $request) + { + return new RootProductCriteria($request->getValue()['model']->getId()); + } + + public function convertFromServiceResult($result, ResolveRequestInterface $request) + { + return $result->getLinkedProducts(); + } +} +``` + +The `getServiceContract()` method points to the service contract to be used. + +The `convertToServiceArgument()` method converts GraphQL requests to a criteria item to be passed in a list as the argument to the contract. Remember that batch service contract methods must accept a single argument: a list (array) of criteria objects. + +The `convertFromServiceResult()` method converts one of the result items into a GraphQL response (a [`\Magento\Framework\GraphQl\Query\Resolver\Value`]({{ site.mage2bloburl }}/{{ page.guide_version }}/lib/internal/Magento/Framework/GraphQl/Query/Resolver/Value.php) instance or an array). Remember that batch service contracts must return result items in the same order as were the criteria items passed as the method's list argument. + +The batch service contract used in the example would look something like this: + +```php +class ProductLinksRetriever +{ + ... + + /** + * @param RootProductCriteria[] $criteriaList + * @return RelatedProductsFound[] + */ + public function getRelatedProducts(array $criteriaList): array + { + .... + } +} + +class RootProductCriteria +{ + .... + + public function __construct(int $rootProductId) + { + $this->productId = $rootProductId; + } + + public function getRootProductId(): int + { + return $this->productId; + } +} + +class RelatedProductsFound +{ + .... + + public function getLinkedProducts(): array + { + .... + } + + public function getRootProductId(): int + { + .... + } +} +``` + +A real example can be found at [\Magento\CatalogGraphQl\Model\Resolver\Product\BatchProductLinks]({{ site.mage2bloburl }}/{{ page.guide_version }}/app/code/Magento/CatalogGraphQl/Model/Resolver/Product/BatchProductLinks.php) + +### ResolverInterface + +This interface resolves one branch or leaf at a time. It returns [`\Magento\Framework\GraphQl\Query\Resolver\Value`]({{ site.mage2bloburl }}/{{ page.guide_version }}/lib/internal/Magento/Framework/GraphQl/Query/Resolver/Value.php) or any type of data (mixed). This value takes in a callable function to its constructor that will be invoked at the latest possible time for the resolver to acquire its data. As a result, a list of items being resolved can be retrieved all at once by establishing a buffer that contains all relevant parent data to filter and fetch for the children list data. You can view an example inside the [`\Magento\BundleGraphQl\Model\Resolver\BundleItemLinks`]({{ site.mage2bloburl }}/{{ page.guide_version }}/app/code/Magento/BundleGraphQl/Model/Resolver/BundleItemLinks.php) resolver. This resolver takes each bundle option ID and its corresponding parent product ID and stores them in a collection's filter buffer (in this case, using the [`\Magento\BundleGraphQl\Model\Resolver\Links\Collection::addIdFilters()`]({{ site.mage2bloburl }}/{{ page.guide_version }}/app/code/Magento/BundleGraphQl/Model/Resolver/Links/Collection.php#L62-L70) function). Each resolver then returns a callable that invokes this collection. The collection caches the result of all link entities it fetched for all the option_id/parent_id combinations. This fetch only needs to occur once for the whole `BundleItemLink` list, and each resulting callable that is invoked for every link in the list returns an item from the collections cached result. @@ -97,7 +248,8 @@ type InputParamsType { ``` ### Resolver class -Use the following sample code as a template for the GraphQl resolver query/mutation class + +Use the following sample code as a template for the GraphQL resolver mutation class: ```php /downloadable/download/sample/sample_id/16/" + }, + { + "title": "Trailer #2", + "sample_url": "https:///downloadable/download/sample/sample_id/17/" + }, + { + "title": "Trailer #3", + "sample_url": "https:///downloadable/download/sample/sample_id/18/" + } + ] + } + ] + } + } + } +} +``` + +### Add a downloadable product to a cart with disabled `Links can be purchased separately` + +The following example shows how to add a downloadable product in which the **Links can be purchased separately** option is disabled. All downloadable links are added to the cart automatically. + +**Request:** + +```graphql +mutation { + addDownloadableProductsToCart( + input: { + cart_id: "gMV2BFQuNGiQmTnepQlMGko7Xc4P3X1w" + cart_items: { + data: { + sku: "240-LV07" + quantity: 1 + } + } + } + ) { + cart { + items { + product { + sku + } + quantity + ... on DownloadableCartItem { + links { + title + price + } + samples { + title + sample_url + } + } + } + } + } +} +``` + +**Response:** + +```text +{ + "data": { + "addDownloadableProductsToCart": { + "cart": { + "items": [ + { + "product": { + "sku": "240-LV07" + }, + "quantity": 2, + "links": [ + { + "title": "Solo Power Circuit", + "price": 14 + } + ], + "samples": [ + { + "title": "Trailer #1", + "sample_url": "https:///downloadable/download/sample/sample_id/10/" + }, + { + "title": "Trailer #2", + "sample_url": "https:///downloadable/download/sample/sample_id/11/" + }, + { + "title": "Trailer #3", + "sample_url": "https:///downloadable/download/sample/sample_id/12/" + } + ] + } + ] + } + } + } +} +``` + +## Input attributes + +The top-level `AddDownloadableProductsToCartInput` object is listed first. All child objects are listed in alphabetical order. + +### AddDownloadableProductsToCartInput object {#AddDownloadableProductsToCartInput} + +The `AddDownloadableProductsToCartInput` object must contain the following attributes: + +Attribute | Data Type | Description +--- | --- | --- +`cart_id` | String! | The unique ID that identifies the customer's cart +`cart_items` | [[DownloadableProductCartItemInput!]!](#DownloadableProductCartItemInput) | Contains the cart item IDs and quantity of each item + +### CartItemInput object {#CartItemInputVirtual} + +The `CartItemInput` object must contain the following attributes: + +{% include graphql/cart-item-input.md %} + +### CustomizableOptionInput object {#CustomizableOptionInputVirtual} + +The `CustomizableOptionInput` object must contain the following attributes: + +{% include graphql/customizable-option-input.md %} + +### DownloadableProductCartItemInput object {#DownloadableProductCartItemInput} + +The `DownloadableProductCartItemInput` object can contain the following attribute: + +Attribute | Data Type | Description +--- | --- | --- +`customizable_options` |[[CustomizableOptionInput!]](#CustomizableOptionInputVirtual) | An array that defines customizable options for the product +`data` | [CartItemInput!](#CartItemInputVirtual) | Required. An object containing the `sku` and `quantity` of the product +`downloadable_product_links` | [[DownloadableProductLinksInput!]](#DownloadableProductLinksInput) | An object containing the `link_id` of the downloadable product link + +### DownloadableProductLinksInput object {#DownloadableProductLinksInput} + +If specified, the `DownloadableProductLinksInput` object must contain the following attribute. + +Attribute | Data Type | Description +--- | --- | --- +`link_id` | Int! | A unique ID (`downloadable_link`.`link_id`) of the downloadable product link + +## Output attributes + +The `AddDownloadableProductsToCartOutput` object contains the `Cart` object. + +Attribute | Data Type | Description +--- | --- | --- +`cart` |[Cart!](#CartObject) | Describes the contents of the specified shopping cart + +### Cart object {#CartObject} + +{% include graphql/cart-object.md %} + +## Errors + +Error | Description +--- | --- +`Required parameter "cart_id" is missing` | The mutation does not contain a `cart_id` parameter. +`Required parameter "cart_items" is missing` | The `cart_items` parameter is empty or is not of type `array`. +`Please specify product link(s).` | You tried to add a downloadable product in which the `Links can be purchased separately` option is enabled, but you did not specify individual product links. diff --git a/src/guides/v2.3/graphql/mutations/create-customer-address.md b/src/guides/v2.3/graphql/mutations/create-customer-address.md index b0c47e1a20c..016fa64c185 100644 --- a/src/guides/v2.3/graphql/mutations/create-customer-address.md +++ b/src/guides/v2.3/graphql/mutations/create-customer-address.md @@ -22,10 +22,9 @@ mutation { createCustomerAddress(input: { region: { region: "Arizona" - region_id: 4 region_code: "AZ" } - country_id: US + country_code: US street: ["123 Main Street"] telephone: "7777777777" postcode: "77777" @@ -42,7 +41,7 @@ mutation { region_id region_code } - country_id + country_code street telephone postcode @@ -63,10 +62,9 @@ mutation { "customer_id": 5, "region": { "region": "Arizona", - "region_id": 4, "region_code": "AZ" }, - "country_id": "US", + "country_code": "US", "street": [ "123 Main Street" ], diff --git a/src/guides/v2.3/graphql/mutations/create-payflow-pro-token.md b/src/guides/v2.3/graphql/mutations/create-payflow-pro-token.md index d9c6a26f542..08880f815b5 100644 --- a/src/guides/v2.3/graphql/mutations/create-payflow-pro-token.md +++ b/src/guides/v2.3/graphql/mutations/create-payflow-pro-token.md @@ -3,13 +3,13 @@ group: graphql title: createPayflowProToken mutation --- -The `createPayflowProToken` mutation initiates a PayFlowPro transaction and receives a token. The payload must contain the redirect URLs to use when the transaction is successful, when the customer cancels the transaction, or when an error occurs. +The `createPayflowProToken` mutation initiates a Payflow Pro transaction and receives a token. The payload must contain the redirect URLs to use when the transaction is successful, when the customer cancels the transaction, or when an error occurs. See [Paypal Payflow Pro payment method]({{page.baseurl}}/graphql/payment-methods/payflow-pro.html) for detailed information about the workflow of PayPal Payflow Pro transactions. ## Syntax -`createPayflowProToken(input: PayflowProTokenInput): PayflowProToken` +`createPayflowProToken(input: PayflowProTokenInput): CreatePayflowProTokenOutput` ## Example usage @@ -83,7 +83,10 @@ Attribute | Data Type | Description ## Output attributes -The `PayflowProToken` object contains the following attributes: +{:.bs-callout-info} +The `createPayflowProToken` mutation previously returned a `PayflowProToken` object, which has been deprecated. The mutation now returns a `CreatePayflowProTokenOutput` object. The contents of these objects are identical. + +The `CreatePayflowProTokenOutput` object contains the following attributes: Attribute | Data Type | Description --- | --- | --- diff --git a/src/guides/v2.3/graphql/mutations/create-paypal-express-token.md b/src/guides/v2.3/graphql/mutations/create-paypal-express-token.md index dc1e3893879..f07e0487363 100644 --- a/src/guides/v2.3/graphql/mutations/create-paypal-express-token.md +++ b/src/guides/v2.3/graphql/mutations/create-paypal-express-token.md @@ -13,7 +13,7 @@ The input includes the cart ID, the payment method code, and a set of URLs that ## Syntax -`mutation: {createPaypalExpressToken(input: PaypalExpressTokenInput!): {PaypalExpressToken}}` +`mutation: {createPaypalExpressToken(input: PaypalExpressTokenInput!): {PaypalExpressTokenOutput}}` ## Example usage @@ -85,7 +85,10 @@ Attribute | Data Type | Description ## Output attributes -### PaypalExpressToken {#PaypalExpressToken} +{:.bs-callout-info} +The `createPaypalExpressToken` mutation previously returned a `PaypalExpressToken` object, which has been deprecated. The mutation now returns a `PaypalExpressTokenOutput` object. The contents of these objects are identical. + +### PaypalExpressTokenOutput {#PaypalExpressTokenOutput} The `PaypalExpressToken` object contains a token returned by PayPal and a set of URLs that allow the buyer to authorize payment and adjust checkout details. diff --git a/src/guides/v2.3/graphql/mutations/merge-carts.md b/src/guides/v2.3/graphql/mutations/merge-carts.md new file mode 100644 index 00000000000..5ea2c35f63e --- /dev/null +++ b/src/guides/v2.3/graphql/mutations/merge-carts.md @@ -0,0 +1,85 @@ +--- +group: graphql +title: mergeCarts mutation +--- + +The `mergeCarts` mutation transfers the contents of a guest cart into the cart of a logged-in customer. This mutation must be run on behalf of a logged-in customer. + +The mutation retains any items that were already in the logged-in customer's cart. If both the guest and customer carts contain the same item, `mergeCarts` adds the quantities. Upon success, the mutation deletes the original guest cart. + +Use the [`customerCart` query]({{page.baseurl}}/graphql/queries/customer-cart.html) to determine the value of the `destination_cart_id` attribute. + +## Syntax + +`mergeCarts(source_cart_id: String!, destination_cart_id: String!): Cart!` + +## Example usage + +In the following example, the customer had one Overnight Duffle in the cart (`CYmiiQRjPVc2gJUc5r7IsBmwegVIFO43`) before a guest cart (`mPKE05OOtcxErbk1Toej6gw6tcuxvT9O`) containing a Radiant Tee and another Overnight Duffle was merged. The cart now includes three items, including two Overnight Duffles. + +**Request:** + +```graphql +mutation { + mergeCarts(source_cart_id: "mPKE05OOtcxErbk1Toej6gw6tcuxvT9O", destination_cart_id: "CYmiiQRjPVc2gJUc5r7IsBmwegVIFO43") { + items { + id + product { + name + sku + } + quantity + } + } +} +``` + +**Response:** + +```json +{ + "data": { + "mergeCarts": { + "items": [ + { + "id": "14", + "product": { + "name": "Overnight Duffle", + "sku": "24-WB07" + }, + "quantity": 2 + }, + { + "id": "17", + "product": { + "name": "Radiant Tee", + "sku": "WS12" + }, + "quantity": 1 + } + ] + } + } +} +``` + +## Input attributes + +Attribute | Data Type | Description +--- | --- | --- +`destination_cart_id` | String! | The ID of the logged-in customer's cart +`source_cart_id` | String! | The ID of the guest cart + +## Output attributes + +The `mergeCarts` mutation returns a `Cart` object. + +Attribute | Data Type | Description +--- | --- | --- +`cart` |[Cart!](#CartObject) | Describes the contents of the specified shopping cart + +### Cart object {#CartObject} + +{% include graphql/cart-object.md %} + +[Cart query output]({{page.baseurl}}/graphql/queries/cart.html#cart-output) provides more information about the `Cart` object. diff --git a/src/guides/v2.3/graphql/mutations/place-order.md b/src/guides/v2.3/graphql/mutations/place-order.md index 18506ca5178..8925e14a9e2 100644 --- a/src/guides/v2.3/graphql/mutations/place-order.md +++ b/src/guides/v2.3/graphql/mutations/place-order.md @@ -33,7 +33,7 @@ mutation { } ) { order { - order_id + order_number } } } @@ -46,7 +46,7 @@ mutation { "data": { "placeOrder": { "order": { - "order_id": "000000006" + "order_number": "000000006" } } } @@ -73,4 +73,5 @@ Attribute | Data Type | Description Attribute | Data Type | Description --- | --- | --- -`order_id` | String | The unique ID that identifies the order +`order_id` | String | Deprecated. Use `order_number` instead +`order_number` String | The unique ID that identifies the order diff --git a/src/guides/v2.3/graphql/mutations/set-billing-address.md b/src/guides/v2.3/graphql/mutations/set-billing-address.md index b3e6c24f4fb..4bb75e83549 100644 --- a/src/guides/v2.3/graphql/mutations/set-billing-address.md +++ b/src/guides/v2.3/graphql/mutations/set-billing-address.md @@ -5,7 +5,7 @@ redirect from: - /guides/v2.3/graphql/reference/quote-set-billing-address.html --- -The `setBillingAddressOnCart` mutation sets the billing address for a specific cart. If you set the `use_for_shipping` attribute to `true`, Magento assigns the same address as the shipping address. +The `setBillingAddressOnCart` mutation sets the billing address for a specific cart. If you set the `same_as_shipping` attribute to `true`, Magento assigns the same address as the shipping address. ## Syntax @@ -35,7 +35,7 @@ mutation { telephone: "8675309" save_in_address_book: true } - use_for_shipping: false + same_as_shipping: false } } ) { @@ -96,7 +96,8 @@ Attribute | Data Type | Description --- | --- | --- `address` | [CartAddressInput](#CartAddressInput) | The billing address for the cart `customer_address_id` | Int | The unique ID that identifies the customer's address -`use_for_shipping` | Boolean | Specifies whether to use the billing address for the shipping address (`True`/`False`) +`same_as_shipping` | Boolean | Specifies whether to use the billing address for the shipping address (`True`/`False`) +`use_for_shipping` | Boolean | Deprecated. Use `same_as_shipping` instead ### CartAddressInput object {#CartAddressInput} diff --git a/src/guides/v2.3/graphql/mutations/set-payment-place-order.md b/src/guides/v2.3/graphql/mutations/set-payment-place-order.md index e59736c66e0..d2d78c14d8a 100644 --- a/src/guides/v2.3/graphql/mutations/set-payment-place-order.md +++ b/src/guides/v2.3/graphql/mutations/set-payment-place-order.md @@ -7,8 +7,8 @@ redirect from: - /guides/v2.3/graphql/reference/quote-set-payment-place-order.html --- - {:.bs-callout-info} -The `setPaymentMethodAndPlaceOrder` mutation will be deprecated in the next patch release. Use the `setPaymentMethodOnCart` and `placeOrder` mutations instead. You can run the two methods in the same call if your use case allows it. +{:.bs-callout-warning} +The `setPaymentMethodAndPlaceOrder` mutation has been deprecated. Use the [setPaymentMethodOnCart]({{page.baseurl}}/graphql/mutations/set-payment-method.html) and [placeOrder]({{page.baseurl}}/graphql/mutations/place-order.html) mutations instead. You can run the two methods in the same call if your use case allows it. The `setPaymentMethodAndPlaceOrder` mutation sets the cart payment method and converts the cart into an order. The mutation returns the resulting order ID. You cannot manage orders with GraphQL, because orders are part of the backend. diff --git a/src/guides/v2.3/graphql/mutations/set-shipping-address.md b/src/guides/v2.3/graphql/mutations/set-shipping-address.md index 0bf00951d23..e3cdc9409c3 100644 --- a/src/guides/v2.3/graphql/mutations/set-shipping-address.md +++ b/src/guides/v2.3/graphql/mutations/set-shipping-address.md @@ -8,7 +8,7 @@ redirect from: The `setShippingAddressesOnCart` mutation sets one or more shipping addresses on a specific cart. The shipping address does not need to be specified in the following circumstances: * The cart contains only virtual items -* When you defined the billing address, you set the `use_for_shipping` attribute to `true`. Magento assigns the same address as the shipping address. +* When you defined the billing address, you set the `same_for_shipping` attribute to `true`. Magento assigns the same address as the shipping address. ## Syntax @@ -92,7 +92,7 @@ The top-level `SetShippingAddressesOnCartInput` object is listed first. All chil Attribute | Data Type | Description --- | --- | --- `cart_id` | String! | The unique ID that identifies the customer's cart -`billing_address` | [ShippingAddressInput!](#ShippingAddressInput) | The billing address for a specific cart +`shipping_addresses` | [ShippingAddressInput!](#ShippingAddressInput) | The shipping address for a specific cart ### CartAddressInput object {#CartAddressInputShip} @@ -104,6 +104,7 @@ Attribute | Data Type | Description --- | --- | --- `address` | [CartAddressInput](#CartAddressInputShip) | The shipping address for the cart `customer_address_id` | Int | The unique ID that identifies the customer's address +`customer_notes` | String | Text provided by the customer ## Output attributes diff --git a/src/guides/v2.3/graphql/product/category-interface.md b/src/guides/v2.3/graphql/product/category-interface.md index 86357547e57..eb65b684ee7 100644 --- a/src/guides/v2.3/graphql/product/category-interface.md +++ b/src/guides/v2.3/graphql/product/category-interface.md @@ -12,6 +12,8 @@ The following table defines the `CategoryInterface` attributes and objects. Attribute | Type | Description --- | --- | --- `breadcrumbs` | [Breadcrumb] | A Breadcrumb object contains information the categories that comprise the breadcrumb trail for the specified category +`canonical_url` | String | The relative canonical URL. This value is returned only if the system setting **Use Canonical Link Meta Tag For Categories** is enabled +`cms_block` | CmsBlock | Contains a category CMS block. This attribute is defined in the `CatalogCmsGraphQl` module `created_at` | String | Timestamp indicating when the category was created `default_sort_by` | String | The attribute to use for sorting `description` | String | An optional description of the category @@ -56,3 +58,7 @@ Attribute | Data type | Description `items` | [ProductInterface] | An array of products that are assigned to the category. See [ProductInterface]({{ page.baseurl }}/graphql/product/product-interface.html) for more information `page_info` | `SearchResultPageInfo` | An object that includes the `page_info` and `currentPage` values specified in the query `total_count` | Int | The number of products returned + +### CmsBlock attributes + +{% include graphql/cms-block-object.md %} diff --git a/src/guides/v2.3/graphql/product/downloadable-product.md b/src/guides/v2.3/graphql/product/downloadable-product.md index e8bc71fa085..ab033160279 100644 --- a/src/guides/v2.3/graphql/product/downloadable-product.md +++ b/src/guides/v2.3/graphql/product/downloadable-product.md @@ -24,7 +24,7 @@ The `DownloadableProductSamples` object contains the following attributes: Attribute | Type | Description --- | --- | --- -`id` | Int | Deprecated. This information should not be exposed on frontend +`id` | Int | Deprecated. This attribute is not applicable for GraphQL `sample_file` | String | Deprecated. Use `sample_url` instead `sample_type` | DownloadableFileTypeEnum | Deprecated. Use `sample_url` instead `sample_url` | String | The URL to the downloadable sample @@ -38,9 +38,9 @@ The `DownloadableProductLinks` object contains the following attributes: Attribute | Type | Description --- | --- | --- `id` | Int | Deprecated. This information should not be exposed on frontend -`is_shareable` | Boolean | Deprecated. This information should not be exposed on frontend +`is_shareable` | Boolean | Deprecated. This attribute is not applicable for GraphQL `link_type` | DownloadableFileTypeEnum | Deprecated. Use `sample_url` instead -`number_of_downloads` | Int | Deprecated. This information should not be exposed on frontend +`number_of_downloads` | Int | Deprecated. This attribute is not applicable for GraphQL `price` | Float | The price of the downloadable product `sample_file` | String | Deprecated. Use `sample_url` instead `sample_type` | DownloadableFileTypeEnum | Deprecated. Use `sample_url` instead diff --git a/src/guides/v2.3/graphql/product/product-interface.md b/src/guides/v2.3/graphql/product/product-interface.md index fd7251c1799..fa95dac36a6 100644 --- a/src/guides/v2.3/graphql/product/product-interface.md +++ b/src/guides/v2.3/graphql/product/product-interface.md @@ -21,7 +21,7 @@ The following table defines the `ProductInterface` attributes and objects. Attribute | Data type | Description --- | --- | --- `attribute_set_id` | Int | The attribute set assigned to the product -`canonical_url` | String | The canonical URL for the product +`canonical_url` | String | The relative canonical URL. This value is returned only if the system setting **Use Canonical Link Meta Tag For Products** is enabled `categories` | [[CategoryInterface]]({{ page.baseurl }}/graphql/product/category-interface.html) | The categories assigned to the product. See [CategoryInterface attributes]({{ page.baseurl }}/graphql/product/category-interface.html) for more information `country_of_manufacture` | String | The product's country of origin `created_at` | String | Timestamp indicating when the product was created @@ -42,7 +42,9 @@ Attribute | Data type | Description `new_to_date` | String | The end date for new product listings `only_x_left_in_stock` | Float | The "Only X left Threshold" assigned to the product. This attribute is defined in the `InventoryGraphQl` module. `options_container` | String | If the product has multiple options, determines where they appear on the product page -`price` | ProductPrices | The price of an item. A `ProductPrice` object is returned. See [ProductPrices](#ProductPrices) for more information. +`price` | ProductPrices | Deprecated. Use `price_range` instead +`price_range` | [PriceRange!](#PriceRange) | A `PriceRange` object, indicating the range of prices for the product +`price_tiers` | [TierPrice] | An array of `TierPrice` objects `product_links` | [ProductLinksInterface] | An array of [ProductLinks](#ProductLinks) objects `related_products` | [ProductInterface] | An array of related products `short_description` | ComplexTextValue | An object that contains a short description of the product. Its use depends on the store's theme. The object can include simple HTML tags @@ -55,27 +57,72 @@ Attribute | Data type | Description `swatch_image` | String | The file name of a swatch image. This attribute is defined in the `SwatchesGraphQl` module. `tax_class_id` | Int | An ID assigned to a tax class. This attribute is defined in the `TaxGraphQl` module. `thumbnail` | [ProductImage](#ProductImage) | An object that contains the URL and label for the product's thumbnail image -`tier_price` | Float | The price when tier pricing is in effect and the items purchased threshold has been reached -`tier_prices` | [ProductTierPrices] | An array of [ProductTierPrices](#ProductTier) objects -`type_id` | String | One of `simple`, `virtual`, `bundle`, `downloadable`,`grouped`, `configurable` +`tier_price` | Float | Deprecated. Use `price_tiers` instead +`tier_prices` | [ProductTierPrices] | Deprecated. Use `price_tiers` instead +`type_id` | String | Deprecated. Use the GraphQL `__typename` meta attribute instead `updated_at` | String | The timestamp indicating when the product was last updated `upsell_products` | [ProductInterface] | An array of up-sell products `url_key` | String | The part of the URL that identifies the product. This attribute is defined in the `CatalogUrlRewriteGraphQl` module `url_path` | String | Deprecated. Use `canonical_url` instead +`url_suffix` | String | The part of the URL that is appended to the `url_key`, such as `.html`. This attribute is defined in the `CatalogUrlRewriteGraphQl` module `url_rewrites` | [[UrlRewrite]](#urlRewriteObject) | A list of URL rewrites -`websites` | [[Website]](#websiteObject) | An array of websites in which the product is available +`websites` | [[Website]](#websiteObject) | Deprecated. This attribute is not applicable for GraphQL ### ProductPrices object {#ProductPrices} +{:.bs-callout-info} +The `ProductPrices` object has been deprecated. Use the [`PriceRange`](#PriceRange) object instead. + The `ProductPrices` object contains the regular price of an item, as well as its minimum and maximum prices. Only composite products, which include bundle, configurable, and grouped products, can contain a minimum and maximum price. Attribute | Data Type | Description --- | --- | --- -`maximalPrice` | Price | Used for composite (bundle, configurable, grouped) products. This is the highest possible final price for all the options defined within a composite product. If you're specifying a price range, this would be the "to" value. -`minimalPrice` | Price | Used for composite (bundle, configurable, grouped) products. This is the lowest possible final price for all the options defined within a composite product. If you're specifying a price range, this would be the "from" value. -`regularPrice` | Price | The base price of a product. +`maximalPrice` | Price | Deprecated. Use `PriceRange.maximum_price` instead +`minimalPrice` | Price | Deprecated. Use `PriceRange.minimum_price` instead +`regularPrice` | Price | Deprecated. Use `PriceRange.maximum_price` or `PriceRange.minimum_price` instead + +### PriceRange object {#PriceRange} + +The `PriceRange` object defines the price range for a product. If a product only has a single price, the minimum and maximum price will be the same. + +Attribute | Data Type | Description +--- | --- | --- +`maximum_price` | ProductPrice | The highest possible final price for a product +`minimum_price` | ProductPrice | The lowest possible final price for a product + +### ProductPrice object {#ProductPrice} + +The `ProductPrice` object includes the regular price, final price, and the difference between those two prices. + +Attribute | Data Type | Description +--- | --- | --- +`discount` | ProductDiscount | The amount of the discount applied to the product. It represents the difference between the `final_price` and `regular_price` +`final_price`| Money! | The price of the product after applying discounts +`fixed_product_taxes` | [[FixedProductTax](#FixedProductTax)] | An array of fixed product taxes that either have been or can be applied to a product price +`regular_price` | Money! | The regular price of the product, without any applied discounts + +### ProductDiscount object {#ProductDiscount} + +The `ProductDiscount` object expresses the discount applied to a product as a fixed amount, such as $5, and as a percentage, such as 10%. The discount originates from special pricing or a catalog price rule. + +Attribute | Data Type | Description +--- | --- | --- +`amount_off` | Float | The actual value of the discount +`percent_off` | Float | The discount expressed as a percentage + +### FixedProductTax object {#FixedProductTax} + +Some tax jurisdictions have a fixed product tax (FPT) that must be applied to certain types of products. An example FPT is the Waste Electrical and Electronic Equipment (WEEE) tax, which is collected on some types of electronics to offset the cost of recycling. + +Attribute | Data Type | Description +--- | --- | --- +`amount` | Money | The amount of the fixed product tax +`label` | String | The label assigned to the fixed product tax to be displayed on the frontend -#### Price object {#Price} +### Price object {#Price} + +{:.bs-callout-info} +The `Price` object has been deprecated. Use the [`ProductPrice`](#ProductPrice) object instead. The `Price` object defines the price of a product as well as any tax-related adjustments. @@ -84,7 +131,7 @@ Attribute | Data Type | Description `amount` | Money | The price of the product and its currency code. See [Money object](#Money). `adjustments` | [PriceAdjustment] | An array of [PriceAdjustment](#PriceAdjustment) objects. -##### Money object {#Money} +#### Money object {#Money} A `Money` object defines a monetary value, including a numeric value and a currency code. @@ -93,9 +140,12 @@ Attribute | Data Type | Description `currency` | CurrencyEnum | A three-letter currency code, such as `USD` or `EUR`. `value` | Float | The price of the product -##### PriceAdjustment array {#PriceAdjustment} +#### PriceAdjustment array {#PriceAdjustment} + +{:.bs-callout-info} +The `PriceAdjustment` object has been deprecated. In cases where the value for the `code` attribute was `WEEE`, use `fixed_product_taxes.label` instead. If the value was `tax` or `weee_tax`, the taxes will be included or excluded as part of the price in the `ProductPrice` or `FixedProductTax` object, respectively. -The `PricedAdjustment` object defines the amount of money to apply as an adjustment, the type of adjustment to apply, and whether the item is included or excluded from the adjustment. +The `PriceAdjustment` object defines the amount of money to apply as an adjustment, the type of adjustment to apply, and whether the item is included or excluded from the adjustment. Attribute | Data Type | Description --- | --- | --- @@ -177,76 +227,48 @@ Attribute | Type | Description ### ProductTierPrices object {#ProductTier} -The `ProductTierPrices` object defines a tier price, which is a quantity discount offered to a specific customer group. +{:.bs-callout-info} +The `ProductTierPrices` object and all of its attributes have been deprecated. Use [`TierPrice`](#TierPrice) instead. -Attribute | Type | Description ---- | --- | --- -`customer_group_id` | Int | The ID of the customer group -`percentage_value` | Float | The percentage discount of the item -`qty` | Float | The number of items that must be purchased to qualify for tier pricing -`value` | Float | The price of the fixed price item -`website_id` | Int | The ID assigned to the website - -## PhysicalProductInterface {#PhysicalProductInterface} - -`PhysicalProductInterface`defines the weight of all tangible products. - -Attribute | Type | Description ---- | --- | --- -`weight` | Float | The weight of the item, in units defined by the store - -## LayerFilter object - -The `LayerFilter` object can be returned in a response to help create layered navigation on your app. - -Attribute | Type | Description ---- | --- | --- -`filter_items` | [LayerFilterItemInterface] | An array of filter items -`filter_items_count` | Int | The number of filter items in filter group -`name` | String | The layered navigation filter name -`request_var` | String | The request variable name for the filter query - -### LayerFilterItemInterface - -`LayerFilterItemInterface` contains an array of items that match the terms defined in the filter. +The `ProductTierPrices` object defines a tier price, which is a quantity discount offered to a specific customer group. Attribute | Type | Description --- | --- | --- -`items_count` | Int | The number of items the filter returned -`label` | String | The label applied to a filter -`value_string` | String | The value for filter request variable to be used in a query +`customer_group_id` | Int | Deprecated. This attribute is not applicable for GraphQL +`percentage_value` | Float | Deprecated. Use `TierPrice.discount` instead +`qty` | Float | Deprecated. Use `TierPrice.quantity` instead +`value` | Float | Deprecated. Use `TierPrice.final_price` instead +`website_id` | Int | Deprecated. This attribute is not applicable for GraphQL -## SortFields object +### TierPrice object {#TierPrice} -The `SortFields` object contains the default value for sort fields as well as all possible sort fields. +The `TierPrice` object defines a tier price, which is a price based on the quantity purchased. Attribute | Type | Description --- | --- | --- -`default` | String | The default sort field -`options` | `SortField` | An array that contains all the fields you can use for sorting - -### SortField object - -Attribute | Type | Description ---- | --- | --- -`label` | String | The attribute's label -`value` | String | The attribute name or code to use as the sort field +`discount` | ProductDiscount | The price discount applied to this tier +`final_price`| Money! | The price of the product at this tier +`quantity` | Float | The minimum number of items that must be purchased to qualify for this price tier ### Website object {#websiteObject} -Use the `Website` attributes to retrieve information about the website's configuration, which includes the website name, website code, and default group ID. +{:.bs-callout-info} +The `Website` object has been deprecated because it is not applicable for GraphQL. + +Use the `Website` attributes to retrieve information about the website's configuration, which includes the website name, website code, and default group ID. The `Website` object is defined in the StoreGraphQl module. Attribute | Data Type | Description --- | --- | --- `code` | String | A code assigned to the website to identify it `default_group_id` | String | The default group ID that the website has `id` | Integer | The ID number assigned to the store -`name` | String | The website name. Websites use this name to identify it easier. +`is_default` | Boolean | Indicates whether this is the default website +`name` | String | The website name. Websites use this name to identify it easier `sort_order` | Integer | The attribute to use for sorting websites ### UrlRewrite object {#urlRewriteObject} -The `products` query can request details about the `UrlRewrite` object. +The `products` query can request details about the `UrlRewrite` object. This object is defined in the UrlRewriteGraphQl module. Attribute | Type | Description --- | --- | --- @@ -261,3 +283,11 @@ Attribute | Type | Description --- | --- | --- `name` | String | The parameter name, such as `id` `value` | String | The value assigned to the parameter + +## PhysicalProductInterface {#PhysicalProductInterface} + +`PhysicalProductInterface`defines the weight of all tangible products. + +Attribute | Type | Description +--- | --- | --- +`weight` | Float | The weight of the item, in units defined by the store diff --git a/src/guides/v2.3/graphql/queries/cart.md b/src/guides/v2.3/graphql/queries/cart.md index db725a6a195..53b7e322f8c 100644 --- a/src/guides/v2.3/graphql/queries/cart.md +++ b/src/guides/v2.3/graphql/queries/cart.md @@ -17,24 +17,25 @@ Cart functionality is defined in the `Quote` module. A Quote represents the cont `{cart(cart_id: String!) {Cart}}` -## Example usage +## Sample queries + +### Cart ready for checkout The following query shows the status of a cart that is ready to be converted into an order. **Request:** -```text -query { - cart(cart_id: "IeTUiU0oCXjm0uRqGCOuhQ2AuQatogjG") - { +```graphql +{ + cart(cart_id: "CYmiiQRjPVc2gJUc5r7IsBmwegVIFO43") { email billing_address { - city - country { - code - label + city + country { + code + label } - firstname + firstname lastname postcode region { @@ -64,10 +65,6 @@ query { value } available - base_amount { - value - currency - } carrier_code carrier_title error_message @@ -87,25 +84,20 @@ query { value currency } - base_amount { - value - currency - } carrier_code carrier_title method_code method_title } - } items { - id - product { - name - sku - } - quantity + id + product { + name + sku } + quantity + } available_payment_methods { code title @@ -114,15 +106,15 @@ query { code title } - applied_coupon { + applied_coupons { code } - prices { - grand_total{ - value - currency - } + prices { + grand_total { + value + currency } + } } } ``` @@ -133,221 +125,87 @@ query { { "data": { "cart": { - "email": "mshaw@example.com", + "email": "roni_cost@example.com", "billing_address": { "city": "Calder", "country": { "code": "US", "label": "US" }, - "firstname": "Bob", - "lastname": "Roll", - "postcode": "49628", + "firstname": "Veronica", + "lastname": "Costello", + "postcode": "49628-7978", "region": { "code": "MI", "label": "Michigan" }, "street": [ - "Magento Pkwy", - "Main Street" + "6146 Honey Bluff Parkway" ], - "telephone": "8675309" + "telephone": "(555) 229-3326" }, "shipping_addresses": [ { - "firstname": "Bob", - "lastname": "Roll", + "firstname": "Veronica", + "lastname": "Costello", "street": [ - "Magento Pkwy", - "Main Street" + "6146 Honey Bluff Parkway" ], - "city": "Austin", + "city": "Calder", "region": { - "code": "TX", - "label": "Texas" + "code": "MI", + "label": "Michigan" }, "country": { "code": "US", "label": "US" }, - "telephone": "8675309", + "telephone": "(555) 229-3326", "available_shipping_methods": [ { "amount": { "currency": "USD", - "value": 20 + "value": 10 }, "available": true, - "base_amount": { - "value": 20, - "currency": "USD" - }, - "carrier_code": "flatrate", - "carrier_title": "Flat Rate", - "error_message": "", - "method_code": "flatrate", - "method_title": "Fixed", - "price_excl_tax": { - "value": 20, - "currency": "USD" - }, - "price_incl_tax": { - "value": 20, - "currency": "USD" - } - }, - { - "amount": { - "currency": "USD", - "value": 5 - }, - "available": true, - "base_amount": { - "value": 5, - "currency": "USD" - }, "carrier_code": "tablerate", "carrier_title": "Best Way", "error_message": "", "method_code": "bestway", "method_title": "Table Rate", "price_excl_tax": { - "value": 5, - "currency": "USD" - }, - "price_incl_tax": { - "value": 5, - "currency": "USD" - } - }, - { - "amount": { - "currency": "USD", - "value": 11.41 - }, - "available": true, - "base_amount": { - "value": 11.41, - "currency": "USD" - }, - "carrier_code": "ups", - "carrier_title": "United Parcel Service", - "error_message": "", - "method_code": "03", - "method_title": "UPS Ground", - "price_excl_tax": { - "value": 11.41, + "value": 10, "currency": "USD" }, "price_incl_tax": { - "value": 11.41, + "value": 10, "currency": "USD" } }, { "amount": { "currency": "USD", - "value": 26.81 + "value": 15 }, "available": true, - "base_amount": { - "value": 26.81, - "currency": "USD" - }, - "carrier_code": "ups", - "carrier_title": "United Parcel Service", - "error_message": "", - "method_code": "12", - "method_title": "UPS Three-Day Select", - "price_excl_tax": { - "value": 26.81, - "currency": "USD" - }, - "price_incl_tax": { - "value": 26.81, - "currency": "USD" - } - }, - { - "amount": { - "currency": "USD", - "value": 34.27 - }, - "available": true, - "base_amount": { - "value": 34.27, - "currency": "USD" - }, - "carrier_code": "ups", - "carrier_title": "United Parcel Service", - "error_message": "", - "method_code": "02", - "method_title": "UPS Second Day Air", - "price_excl_tax": { - "value": 34.27, - "currency": "USD" - }, - "price_incl_tax": { - "value": 34.27, - "currency": "USD" - } - }, - { - "amount": { - "currency": "USD", - "value": 76.12 - }, - "available": true, - "base_amount": { - "value": 76.12, - "currency": "USD" - }, - "carrier_code": "ups", - "carrier_title": "United Parcel Service", - "error_message": "", - "method_code": "01", - "method_title": "UPS Next Day Air", - "price_excl_tax": { - "value": 76.12, - "currency": "USD" - }, - "price_incl_tax": { - "value": 76.12, - "currency": "USD" - } - }, - { - "amount": { - "currency": "USD", - "value": 108.52 - }, - "available": true, - "base_amount": { - "value": 108.52, - "currency": "USD" - }, - "carrier_code": "ups", - "carrier_title": "United Parcel Service", + "carrier_code": "flatrate", + "carrier_title": "Flat Rate", "error_message": "", - "method_code": "14", - "method_title": "UPS Next Day Air Early A.M.", + "method_code": "flatrate", + "method_title": "Fixed", "price_excl_tax": { - "value": 108.52, + "value": 15, "currency": "USD" }, "price_incl_tax": { - "value": 108.52, + "value": 15, "currency": "USD" } } ], "selected_shipping_method": { "amount": { - "value": 5, - "currency": "USD" - }, - "base_amount": { - "value": 5, + "value": 10, "currency": "USD" }, "carrier_code": "tablerate", @@ -359,26 +217,30 @@ query { ], "items": [ { - "id": "13", + "id": "14", "product": { "name": "Strive Shoulder Pack", "sku": "24-MB04" }, - "quantity": 4 + "quantity": 2 + }, + { + "id": "17", + "product": { + "name": "Savvy Shoulder Tote", + "sku": "24-WB05" + }, + "quantity": 1 } ], "available_payment_methods": [ { - "code": "cashondelivery", - "title": "Cash On Delivery" - }, - { - "code": "banktransfer", - "title": "Bank Transfer Payment" + "code": "braintree_cc_vault", + "title": "Stored Cards (Braintree)" }, { - "code": "purchaseorder", - "title": "Purchase Order" + "code": "braintree", + "title": "Credit Card (Braintree)" }, { "code": "checkmo", @@ -386,13 +248,13 @@ query { } ], "selected_payment_method": { - "code": "banktransfer", - "title": "Bank Transfer Payment" + "code": "checkmo", + "title": "Check / Money order" }, - "applied_coupon": null, + "applied_coupons": null, "prices": { "grand_total": { - "value": 133, + "value": 105.26, "currency": "USD" } } @@ -401,6 +263,303 @@ query { } ``` +### Cart discounts + +In this query, the **Buy 3 tee shirts and get the 4th free** cart price rule from the sample data is active. This rule was modified slightly to add the label `3T1free`. (If a cart price rule does not have a label, Magento returns a default label of `Discount`.) A custom rule in which the customer saves 10% on the order by applying a discount code is also in effect. + +The `3T1free` rule is applied first, and Magento returns the price of a single shirt, $29, as the discount. Magento then applies a 10% discount to the remaining total of the products in the cart. + +**Request:** + +```graphql +{ + cart(cart_id: "v7jYJUjvPeHbdMJRcOfZIeQhs2Xc2ZKT") { + email + items { + id + prices { + total_item_discount { + value + } + price { + value + } + discounts { + label + amount { + value + } + } + } + product { + name + sku + } + quantity + } + applied_coupons { + code + } + prices { + discounts { + amount { + value + } + label + } + grand_total { + value + } + } + } +} +``` + +**Response:** + +```json +{ + "data": { + "cart": { + "email": "roni_cost@example.com", + "items": [ + { + "id": "43", + "prices": { + "total_item_discount": { + "value": 37.7 + }, + "price": { + "value": 29 + }, + "discounts": [ + { + "label": "3T1free", + "amount": { + "value": 29 + } + }, + { + "label": "10% Off for New Customers", + "amount": { + "value": 8.7 + } + } + ] + }, + "product": { + "name": "Elisa EverCool™ Tee", + "sku": "WS06" + }, + "quantity": 4 + } + ], + "applied_coupons": [ + { + "code": "NEW" + } + ], + "prices": { + "discounts": [ + { + "amount": { + "value": 29 + }, + "label": "3T1free" + }, + { + "amount": { + "value": 8.7 + }, + "label": "10% Off for New Customers" + } + ], + "grand_total": { + "value": 84.76 + } + } + } + } +} +``` + +### Tier price example + +In the following example, tier prices has been established for product `24-UG01` and `24-UG05`, as shown in the following table: + +Product | Quantity | Fixed/Discount | Amount +--- | --- | --- | --- | +24-UG01 | 5 | Discount | 5% +24-UG01 | 10 | Discount | 10% +24-UG01 | 15 | Discount | 15% +24-UG05 | 5 | Fixed | $16 +24-UG05 | 10 | Fixed | $11 + +The cart in the example contains 12 units of `24-UG05` and 8 units of `24-UG-01`, so the price of `24-UG05` is $11, and the price of `24-UG01` is $18.05 (5% off). + +**Request:** + +```graphql +query { + cart(cart_id: "v7jYJUjvPeHbdMJRcOfZIeQhs2Xc2ZKT"){ + items { + id + quantity + product{ + name + sku + price_tiers { + quantity + final_price { + value + } + discount { + amount_off + percent_off + } + } + } + prices{ + price{ + value + } + } + } + prices { + discounts { + label + amount { + value + } + } + subtotal_excluding_tax { + value + } + applied_taxes { + label + amount { + value + } + } + } + } +} +``` + +**Response:** + +```json +{ + "data": { + "cart": { + "items": [ + { + "id": "65", + "quantity": 12, + "product": { + "name": "Go-Get'r Pushup Grips", + "sku": "24-UG05", + "price_tiers": [ + { + "quantity": 5, + "final_price": { + "value": 16 + }, + "discount": { + "amount_off": 3, + "percent_off": 15.79 + } + }, + { + "quantity": 10, + "final_price": { + "value": 11 + }, + "discount": { + "amount_off": 8, + "percent_off": 42.11 + } + } + ] + }, + "prices": { + "price": { + "value": 11 + } + } + }, + { + "id": "66", + "quantity": 8, + "product": { + "name": "Quest Lumaflex™ Band", + "sku": "24-UG01", + "price_tiers": [ + { + "quantity": 5, + "final_price": { + "value": 18.05 + }, + "discount": { + "amount_off": 0.95, + "percent_off": 5 + } + }, + { + "quantity": 10, + "final_price": { + "value": 17.1 + }, + "discount": { + "amount_off": 1.9, + "percent_off": 10 + } + }, + { + "quantity": 15, + "final_price": { + "value": 16.15 + }, + "discount": { + "amount_off": 2.85, + "percent_off": 15 + } + } + ] + }, + "prices": { + "price": { + "value": 18.05 + } + } + } + ], + "prices": { + "discounts": [ + { + "label": "200", + "amount": { + "value": 55.28 + } + } + ], + "subtotal_excluding_tax": { + "value": 276.4 + }, + "applied_taxes": [ + { + "label": "US-MI-*-Rate 1", + "amount": { + "value": 18.24 + } + } + ] + } + } + } +} +``` + ## Input attributes Attribute | Data Type | Description @@ -482,8 +641,8 @@ The `CartAddressCountry` object can contain the following attributes. Attribute | Data Type | Description --- | --- | --- -`code` | String | The country code -`label` | String | The display label for the country +`code` | String! | The country code +`label` | String! | The display label for the country ### CartAddressInterface {#CartAddressInterface} @@ -491,16 +650,16 @@ The `CartAddressInterface` contains the following attributes. Attribute | Data Type | Description --- | --- | --- -`city` | String | The city specified for the billing address +`city` | String! | The city specified for the billing address `company` | String | The company specified for the billing address -`country` | [CartAddressCountry](#CartAddressCountry) | The country code and label for the billing address +`country` | [CartAddressCountry!](#CartAddressCountry) | The country code and label for the billing address `customer_notes` | String | Comments made to the customer that accompanies the order -`firstname` | String | The customer's first name -`lastname` | String | The customer's last name +`firstname` | String! | The customer's first name +`lastname` | String! | The customer's last name `postcode` | String | The postal code for the billing address `region` | [CartAddressRegion](#CartAddressRegion) | An object containing the region label and code -`street` | [String] | The street for the billing address -`telephone` | String | The telephone number for the billing address +`street` | [String!]! | The street for the billing address +`telephone` | String! | The telephone number for the billing address ### CartAddressRegion object {#CartAddressRegion} @@ -508,8 +667,8 @@ The `CartAddressRegion` object can contain the following attributes. Attribute | Data Type | Description --- | --- | --- -`code` | String | The state or province code -`label` | String | The display label for the region +`code` | String! | The state or province code +`label` | String! | The display label for the region ### CartDiscount object {#CartDiscount} @@ -527,17 +686,30 @@ The `CartItemInterface` can contain the following attributes. Attribute | Data Type | Description --- | --- | --- `id` | String | ID of the item +`prices` | [CartItemPrices](#CartItemPrices) | Includes the price of an item, any applied discounts, and calculated totals `product` | [ProductInterface]({{ page.baseurl }}/graphql/product/product-interface.html) | Contains attributes that are common to all types of products `quantity` | Float | The number of items in the cart +### CartItemPrices object {#CartItemPrices} + +The `CartItemPrices` object can contain the following attributes. + +Attribute | Data Type | Description +--- | --- | --- +`discounts`| [Discount] | An array of discounts to be applied to the cart item +`price` | Money! | The price of the item before any discounts were applied +`row_total` | Money! | The value of the `price` multiplied by the quantity of the item +`row_total_including_tax` | Money! | The value of `row_total` plus the tax applied to the item +`total_item_discount` | Money | The total of all discounts applied to the item + ### CartItemQuantity object {#CartItemQuantity} -The `CartItemQuantity` object must contain the following attributes. +The `CartItemQuantity` data type has been deprecated. Use the `cart_items_v2` attribute with the [`CartItemInterface`](#CartItemInterface) instead. Attribute | Data Type | Description --- | --- | --- -`cart_item_id` | Int! | The unique ID assigned when a customer places an item in the cart -`quantity` | Float! | The quantity of this item selected +`cart_item_id` | Int! | Deprecated. Use `CartItemInterface.id` instead +`quantity` | Float! | Deprecated. Use `CartItemInterface.quantity` instead ### CartPrices object {#CartPrices} @@ -546,7 +718,8 @@ The `CartPrices` object can contain the following attributes. Attribute | Data Type | Description --- | --- | --- `applied_taxes` | [[CartTaxItem]](#CartTaxItem) | An array containing the names and amounts of taxes applied to the item -`discount` | CartDiscount | The total amount of all discounts applied to the cart +`discount` | CartDiscount | Deprecated. Use `discounts` instead +`discounts` | [Discount] | An array containing all discounts applied to the cart `grand_total` | Money | The total, including discounts, taxes, shipping, and other fees `subtotal_excluding_tax` | Money | Subtotal without taxes `subtotal_including_tax` | Money | Subtotal with taxes @@ -561,6 +734,19 @@ Attribute | Data Type | Description `amount` | Money! | The amount of tax applied to the item `label` | String! | The description of the tax +### Discount object {#Discount} + +A discount can be applied to the cart as a whole or to an item. + +If a cart rule does not have a label, Magento uses `Discount` as the default label. + +The `Discount` object must contain the following attributes. + +Attribute | Data Type | Description +--- | --- | --- +`amount` | Money! | The amount of the discount applied to the cart +`label` | String! | The description of the discount + ### SelectedPaymentMethod object {#SelectedPaymentMethod} The `SelectedPaymentMethod` object can contain the following attributes. @@ -577,12 +763,12 @@ The `SelectedShippingMethod` object can contain the following attributes. Attribute | Data Type | Description --- | --- | --- -`amount` | Money | The cost of shipping using this shipping method -`base_amount` | Money | The base shipping cost, not including taxes or other cost adjustment -`carrier_code` | String | A string that identifies a commercial carrier or an offline shipping method -`carrier_title` | String | The label for the carrier code -`method_code` | String | A shipping method code associated with a carrier -`method_title` | String | The label for the method code +`amount` | Money! | The cost of shipping using this shipping method +`base_amount` | Money | Deprecated. This attribute is not applicable for GraphQL +`carrier_code` | String! | A string that identifies a commercial carrier or an offline shipping method +`carrier_title` | String! | The label for the carrier code +`method_code` | String! | A shipping method code associated with a carrier +`method_title` | String! | The label for the method code ### ShippingCartAddress object {#ShippingCartAddress} @@ -591,8 +777,9 @@ The `ShippingCartAddress` object implements [`CartAddressInterface`](#CartAddres Attribute | Data Type | Description --- | --- | --- `available_shipping_methods` | [[AvailableShippingMethod]](#AvailableShippingMethod) | An array that lists the shipping methods that can be applied to the cart -`cart_items` | [[CartItemQuantity]](#CartItemQuantity) | An array that lists the items in the cart -`items_weight` | Float | The weight of all items in the cart +`cart_items` | [[CartItemQuantity]](#CartItemQuantity) | Deprecated. Use `cart_items_v2` instead +`cart_items_v2` | [CartItemInterface] | An array that lists the items in the cart +`items_weight` | Float | Deprecated. This attribute is not applicable for GraphQL `selected_shipping_method` | [SelectedShippingMethod](#SelectedShippingMethod) | An object that describes the selected shipping method ## Related topics diff --git a/src/guides/v2.3/graphql/queries/category-list.md b/src/guides/v2.3/graphql/queries/category-list.md new file mode 100644 index 00000000000..716b66211d3 --- /dev/null +++ b/src/guides/v2.3/graphql/queries/category-list.md @@ -0,0 +1,320 @@ +--- +group: graphql +title: categoryList query +--- + +The `categoryList` query searches for categories that match the criteria specified in filters. It replaces the deprecated `category` query, which allowed you to search by category ID only. + +The `categoryList` query supports the following types of filters. You can specify multiple filters in a query. + +- Category ID +- Category name +- URL Key + +If you do not provide any filter input, the query returns the root category. + +The query returns a `CategoryTree` object. The top level of the `CategoryTree` object provides details about the queried category. This object includes the `children` attribute, which contains an array of its immediate subcategories. To return multiple category levels in a single call, define the response so that it contains up to ten nested `children` options. + +{:.bs-callout-info} +You cannot return the entire category tree if it contains more than ten sublevels unless the `queryDepth` parameter in the GraphQL `di.xml` file has been reconfigured. + +Use the `breadcrumbs` attribute to return information about the parent categories of the queried category. + +## Syntax + +```graphql +categoryList ( + filters: CategoryFilterInput +): CategoryTree +``` + +## Example usage + +### Return the category tree of a top-level category + +The following query returns information about category IDs `11` and `20` and two levels of subcategories. In the sample data, category IDs `11` and `20` are assigned to the `Men` and `Women` categories, respectively. + +**Request:** + +```graphql +{ + categoryList(filters: {ids: {in: ["11", "20"]}}) { + children_count + children { + id + level + name + path + url_path + url_key + children { + id + level + name + path + url_path + url_key + } + } + } +} +``` + +**Response:** + +```json +{ + "data": { + "categoryList": [ + { + "children_count": "8", + "children": [ + { + "id": 13, + "level": 3, + "name": "Bottoms", + "path": "1/2/11/13", + "url_path": "men/bottoms-men", + "url_key": "bottoms-men", + "children": [ + { + "id": 18, + "level": 4, + "name": "Pants", + "path": "1/2/11/13/18", + "url_path": "men/bottoms-men/pants-men", + "url_key": "pants-men" + }, + { + "id": 19, + "level": 4, + "name": "Shorts", + "path": "1/2/11/13/19", + "url_path": "men/bottoms-men/shorts-men", + "url_key": "shorts-men" + } + ] + }, + { + "id": 12, + "level": 3, + "name": "Tops", + "path": "1/2/11/12", + "url_path": "men/tops-men", + "url_key": "tops-men", + "children": [ + { + "id": 14, + "level": 4, + "name": "Jackets", + "path": "1/2/11/12/14", + "url_path": "men/tops-men/jackets-men", + "url_key": "jackets-men" + }, + { + "id": 15, + "level": 4, + "name": "Hoodies & Sweatshirts", + "path": "1/2/11/12/15", + "url_path": "men/tops-men/hoodies-and-sweatshirts-men", + "url_key": "hoodies-and-sweatshirts-men" + }, + { + "id": 16, + "level": 4, + "name": "Tees", + "path": "1/2/11/12/16", + "url_path": "men/tops-men/tees-men", + "url_key": "tees-men" + }, + { + "id": 17, + "level": 4, + "name": "Tanks", + "path": "1/2/11/12/17", + "url_path": "men/tops-men/tanks-men", + "url_key": "tanks-men" + } + ] + } + ] + }, + { + "children_count": "8", + "children": [ + { + "id": 22, + "level": 3, + "name": "Bottoms", + "path": "1/2/20/22", + "url_path": "women/bottoms-women", + "url_key": "bottoms-women", + "children": [ + { + "id": 27, + "level": 4, + "name": "Pants", + "path": "1/2/20/22/27", + "url_path": "women/bottoms-women/pants-women", + "url_key": "pants-women" + }, + { + "id": 28, + "level": 4, + "name": "Shorts", + "path": "1/2/20/22/28", + "url_path": "women/bottoms-women/shorts-women", + "url_key": "shorts-women" + } + ] + }, + { + "id": 21, + "level": 3, + "name": "Tops", + "path": "1/2/20/21", + "url_path": "women/tops-women", + "url_key": "tops-women", + "children": [ + { + "id": 23, + "level": 4, + "name": "Jackets", + "path": "1/2/20/21/23", + "url_path": "women/tops-women/jackets-women", + "url_key": "jackets-women" + }, + { + "id": 24, + "level": 4, + "name": "Hoodies & Sweatshirts", + "path": "1/2/20/21/24", + "url_path": "women/tops-women/hoodies-and-sweatshirts-women", + "url_key": "hoodies-and-sweatshirts-women" + }, + { + "id": 25, + "level": 4, + "name": "Tees", + "path": "1/2/20/21/25", + "url_path": "women/tops-women/tees-women", + "url_key": "tees-women" + }, + { + "id": 26, + "level": 4, + "name": "Bras & Tanks", + "path": "1/2/20/21/26", + "url_path": "women/tops-women/tanks-women", + "url_key": "tanks-women" + } + ] + } + ] + } + ] + } +} +``` + +### Return breadcrumb information + +The following query returns breadcrumb information about categories that have the name `Tops`. + +**Request:** + +```graphql +{ + categoryList(filters: {name: {match: "Tops"}}) { + id + level + name + breadcrumbs { + category_id + category_name + category_level + category_url_key + } + } +} +``` + +**Response:** + +```json +{ + "data": { + "categoryList": [ + { + "id": 12, + "level": 3, + "name": "Tops", + "breadcrumbs": [ + { + "category_id": 11, + "category_name": "Men", + "category_level": 2, + "category_url_key": "men" + } + ] + }, + { + "id": 21, + "level": 3, + "name": "Tops", + "breadcrumbs": [ + { + "category_id": 20, + "category_name": "Women", + "category_level": 2, + "category_url_key": "women" + } + ] + } + ] + } +} +``` + +## Input attributes + +You must specify the `filters` attribute as input to your query. + +Attribute | Data type | Description +--- | --- | --- +`filters` | CategoryFilterInput | Contains filter definitions + +### CategoryFilterInput object + +The `CategoryFilterInput` object defines the filters to be used in this query. + +Attribute | Data type | Description +--- | --- | --- +`ids` | FilterEqualTypeInput | Filters by the specified category IDs +`name` | FilterMatchTypeInput | Filters by the display name of the category +`url_key` | FilterEqualTypeInput | Filters by the part of the URL that identifies the category + +### FilterEqualTypeInput object + +Use the `FilterEqualTypeInput` object to construct filters that search by category ID or URL key. + +Attribute | Data type | Description +--- | --- | --- +`eq` | String | Use this attribute to exactly match the specified string. For example, to filter on a specific URL key, specify a value like `shorts-women` +`in` | [String] | Use this attribute to filter on an array of values. For example, to filter on category IDs 4, 5, and 6, specify a value of `["4", "5", "6"]` + +### FilterMatchTypeInput object + +Use the `FilterMatchTypeInput` object to construct a filter that matches the specified display name. + +Attribute | Data type | Description +--- | --- | --- +`match` | String | Use this attribute to perform a fuzzy match on the specified string. For example, to filter on a specific category name, specify a value such as `Tops` + +## Output attributes {#Categories} + +The query returns a `CategoryTree` object, which implements [`CategoryInterface`]({{page.baseurl}}/graphql/product/category-interface.html). The `CategoryTree` object can contain the following attribute and all attributes defined in `CategoryInterface`: + +Attribute | Data type | Description +--- | --- | --- +`children` | `CategoryTree` | An array containing the next level of subcategories. By default, you can specify up to 10 levels of child categories diff --git a/src/guides/v2.3/graphql/queries/category.md b/src/guides/v2.3/graphql/queries/category.md index 563ad532753..5d2dc650599 100644 --- a/src/guides/v2.3/graphql/queries/category.md +++ b/src/guides/v2.3/graphql/queries/category.md @@ -5,6 +5,9 @@ redirect_from: - /guides/v2.3/graphql/reference/categories.html --- +{:.bs-callout-warning} +The `category` query has been deprecated. Use the [categoryList]({{page.baseurl}}/graphql/queries/category-list.html) query instead. + The `category` query allows you to search for a single category definition or the entire category tree. To return multiple category levels in a single call, define the response so that it contains up to ten nested `children` options. You cannot return the entire category tree if it contains more than 10 sublevels unless the `queryDepth` parameter in the GraphQL `di.xml` file has been reconfigured. ## Syntax @@ -15,9 +18,11 @@ category ( ): CategoryTree ``` -## Example Usage +## Example usage + +### Return the category tree of a top-level category -The following query returns information about category ID `20` and four levels of subcategories. In the sample data, category ID `20` is assigned to the "Women" category. +The following query returns information about category ID `20` and four levels of subcategories. In the sample data, category ID `20` is assigned to the `Women` category. **Request:** @@ -138,7 +143,9 @@ The following query returns information about category ID `20` and four levels o } ``` -The following query returns breadcrumb information about the women's tops category (`id` = 25). +### Return breadcrumb information + +The following query returns breadcrumb information about the women's `Tops` category (`id` = 25). **Request:** @@ -174,13 +181,15 @@ The following query returns breadcrumb information about the women's tops catego "category_id": 20, "category_name": "Women", "category_level": 2, - "category_url_key": "women" + "category_url_key": "women", + "category_url_path": "women" }, { "category_id": 21, "category_name": "Tops", "category_level": 3, - "category_url_key": "tops-women" + "category_url_key": "tops-women", + "category_url_path": "women/tops-women" } ] } diff --git a/src/guides/v2.3/graphql/queries/cms-blocks.md b/src/guides/v2.3/graphql/queries/cms-blocks.md index 113a4c1a692..16d319b9c51 100644 --- a/src/guides/v2.3/graphql/queries/cms-blocks.md +++ b/src/guides/v2.3/graphql/queries/cms-blocks.md @@ -56,14 +56,8 @@ Attribute | Data type | Description ## Output attributes -The `CmsBlocks` object contains an array of `items`, each of which can contain the following attributes: +The `CmsBlocks` object contains an array of `items`, each of which can contain a `CmsBlock` object. -Attribute | Data type | Description ---- | --- | --- -`content` | String | The content of the CMS block in raw HTML -`identifier` | String | The CMS block identifier -`title` | String | The title assigned to the CMS block - -## Related topics +### CmsBlock attributes -[cmsPage query]({{page.baseurl}}/graphql/queries/cms-page.html) +{% include graphql/cms-block-object.md %} diff --git a/src/guides/v2.3/graphql/queries/custom-attribute-metadata.md b/src/guides/v2.3/graphql/queries/custom-attribute-metadata.md index cbe9523dc05..84bb8d848dd 100644 --- a/src/guides/v2.3/graphql/queries/custom-attribute-metadata.md +++ b/src/guides/v2.3/graphql/queries/custom-attribute-metadata.md @@ -137,6 +137,7 @@ Attribute | Data Type | Description `attribute_options` | [`AttributeOption`] | An array of attribute options `attribute_type` | String | The data type of the attribute `entity_type` | String | The type of entity that defines the attribute +`input_type` | String | The frontend input type of the attribute ### AttributeOption object diff --git a/src/guides/v2.3/graphql/queries/customer-cart.md b/src/guides/v2.3/graphql/queries/customer-cart.md new file mode 100644 index 00000000000..3358396f727 --- /dev/null +++ b/src/guides/v2.3/graphql/queries/customer-cart.md @@ -0,0 +1,82 @@ +--- +group: graphql +title: customerCart query +--- + +The `customerCart` query returns the active cart for the logged-in customer. If the cart does not exist, the query creates one. The customer's authorization token must be specified in the headers. + +The `customerCart` query differs from the `cart` query in the following ways: + +- The `customerCart` query must be run on behalf of a logged-in customer. If you run this query on behalf of a guest, an exception will be thrown. +- The `cart` query requires a `cart_id` value as input. The `customerCart` query does not take any input parameters. + +You can define the query to return the `id` attribute. You can use the value of this attribute as the `destination_cart_id` input parameter in the [`mergeCarts` mutation]({{page.baseurl}}/graphql/mutations/merge-carts.html). (The `mergeCarts` mutation provides the ability to merge a guest cart with the logged-in customer's cart.) + +{: .bs-callout-tip } +If you know the value of the logged-in customer's cart ID, you can allow the customer to start an order on one device and complete it on another. + +## Syntax + +`customerCart: Cart!` + +## Example usage + +The following query lists the products in the logged-in customer's cart: + +**Request:** + +```graphql +{ + customerCart { + id + items { + id + product { + name + sku + } + quantity + } + } +} +``` + +**Response:** + +```json +{ + "data": { + "customerCart": { + "id": "CYmiiQRjPVc2gJUc5r7IsBmwegVIFO43", + "items": [ + { + "id": "11", + "product": { + "name": "Strive Shoulder Pack", + "sku": "24-MB04" + }, + "quantity": 1 + }, + { + "id": "12", + "product": { + "name": "Radiant Tee", + "sku": "WS12" + }, + "quantity": 1 + } + ] + } + } +} +``` + +## Output attributes + +The `customerCart` query returns the `Cart` object. + +### Cart object {#CartObject} + +{% include graphql/cart-object.md %} + +[Cart query output]({{page.baseurl}}/graphql/queries/cart.html#cart-output) provides more information about the `Cart` object. diff --git a/src/guides/v2.3/graphql/queries/customer-downloadable-products.md b/src/guides/v2.3/graphql/queries/customer-downloadable-products.md index 1a207b2c91c..95bce24b186 100644 --- a/src/guides/v2.3/graphql/queries/customer-downloadable-products.md +++ b/src/guides/v2.3/graphql/queries/customer-downloadable-products.md @@ -38,14 +38,14 @@ The following example returns the list of purchased downloadable products for th "items": [ { "date": "2019-03-04 20:48:32", - "download_url": "http://magento2.vagrant93/downloadable/download/link/id/MC44NTcwMTEwMCAxNTUxNzMyNTEyMTExNTE%2C/", + "download_url": "https:///downloadable/download/link/id/MC44NTcwMTEwMCAxNTUxNzMyNTEyMTExNTE%2C/", "order_increment_id": "000000004", "remaining_downloads": "Unlimited", "status": "pending" }, { "date": "2019-03-04 20:48:32", - "download_url": "http://magento2.vagrant93/downloadable/download/link/id/MC44NzM0OTkwMCAxNTUxNzMyNTEyMjEyNTA%2C/", + "download_url": "https:///downloadable/download/link/id/MC44NzM0OTkwMCAxNTUxNzMyNTEyMjEyNTA%2C/", "order_increment_id": "000000004", "remaining_downloads": "Unlimited", "status": "pending" diff --git a/src/guides/v2.3/graphql/queries/customer-orders.md b/src/guides/v2.3/graphql/queries/customer-orders.md index 5a95212c4b4..db0bca042ea 100644 --- a/src/guides/v2.3/graphql/queries/customer-orders.md +++ b/src/guides/v2.3/graphql/queries/customer-orders.md @@ -23,7 +23,7 @@ The following query returns the order history of the logged in customer. { customerOrders { items { - increment_id + order_number id created_at grand_total @@ -41,14 +41,14 @@ The following query returns the order history of the logged in customer. "customerOrders": { "items": [ { - "increment_id": "000000001", + "order_number": "000000001", "id": 1, "created_at": "2019-02-21 00:24:34", "grand_total": 36.39, "status": "processing" }, { - "increment_id": "000000002", + "order_number": "000000002", "id": 2, "created_at": "2019-02-21 00:24:35", "grand_total": 39.64, @@ -77,7 +77,8 @@ Attribute | Data type | Description `created_at` | String | A timestamp indicating when the order was placed `grand_total` | Float | The total of the order `id` | Int | The ID assigned to the customer's order -`increment_id` | String | An ID that indicates the sequence of the order in the customer's order history +`increment_id` | String | Deprecated. Use `order_number` instead. An ID that indicates the sequence of the order in the customer's order history +`order_number` | String! | The order number assigned to the order `status` | String | The status of the order, such as `open`, `processing`, or `closed` ## Errors diff --git a/src/guides/v2.3/graphql/queries/customer.md b/src/guides/v2.3/graphql/queries/customer.md index 4f506291b60..8ed1478ede7 100644 --- a/src/guides/v2.3/graphql/queries/customer.md +++ b/src/guides/v2.3/graphql/queries/customer.md @@ -40,7 +40,7 @@ The following call returns information about the logged-in customer. Provide the region_id } postcode - country_id + country_code telephone } } @@ -72,7 +72,7 @@ The following call returns information about the logged-in customer. Provide the "region_id": 33 } "postcode": "78758", - "country_id": "US", + "country_code": "US", "telephone": "512 555-1212" } ] @@ -188,7 +188,83 @@ query { } } ``` +### Retrieve the customer's wish list +The following query returns the customer's wish list: + +**Request:** + +```graphql +{ + customer { + wishlist { + items { + id + description + qty + product { + sku + name + price_range { + maximum_price { + regular_price { + value + } + } + } + } + } + } + } +} +``` + +**Response:** + +```json +{ + "data": { + "customer": { + "wishlist": { + "items": [ + { + "id": 1, + "description": "I need this", + "qty": 1, + "product": { + "sku": "24-WG080", + "name": "Sprite Yoga Companion Kit", + "price_range": { + "maximum_price": { + "regular_price": { + "value": 77 + } + } + } + } + }, + { + "id": 2, + "description": null, + "qty": 1, + "product": { + "sku": "24-UG04", + "name": "Zing Jump Rope", + "price_range": { + "maximum_price": { + "regular_price": { + "value": 12 + } + } + } + } + } + ] + } + } + } +} +``` ## Output attributes ### Customer attributes {#customerAttributes} @@ -197,6 +273,26 @@ The `customer` object can contain the following attributes: {% include graphql/customer-output.md %} +### Wishlist attributes {#Wishlist} + +Attribute | Data type | Description +--- | --- | --- +`items` | [WishlistItem](#wishlistitem) | An array of items in the customer's wish list +`items_count` | Int | The number of items in the wish list +`id` | ID | The unique identifier of the wish list +`sharing_code` | String | An encrypted code that Magento uses to link to the wish list +`updated_at` | String | The time of the last modification to the wish list + +### WishlistItem attributes {#wishlistitem} + +Attribute | Data type | Description +--- | --- | --- +`added_at` | String | The time when the customer added the item to the wish list +`description` | String | The customer's comment about this item +`id` | Int | The wish list item ID +`product` | [ProductInterface]({{ page.baseurl }}/graphql/product/product-interface.html) | The ProductInterface contains attributes that are common to all types of products. Note that descriptions may not be available for custom and EAV attributes +`qty` | Float | The quantity of this wish list item + ### Store credit attributes In {{site.data.var.ee}}, the merchant can assign store credit to customers. Magento maintains the history of all changes to the balance of store credit available to the customer. The customer must be logged in to access the store credit history and balance. diff --git a/src/guides/v2.3/graphql/queries/index.md b/src/guides/v2.3/graphql/queries/index.md index 1dc9d8dc692..80be2e27b27 100644 --- a/src/guides/v2.3/graphql/queries/index.md +++ b/src/guides/v2.3/graphql/queries/index.md @@ -1,6 +1,6 @@ --- group: graphql -title: Queries +title: Using queries redirect_from: - /guides/v2.3/graphql/search-pagination.html - /guides/v2.3/graphql/queries.html @@ -13,7 +13,7 @@ A GraphQL query retrieves data from the Magento server in a similar manner as a * Shopping cart contents. GraphQL supports both guest and logged-in customer carts. * Store configuration values, including theme and CMS settings, the currency code, and supported countries. -The Magento REST GET endpoints retrieve a wide variety of information on behalf of the merchant. Many of these endpoints are for retrieving backend information. For example, the `GET /V1/customers/search` endpoint can be used to find a subset of customers that meet certain criteria, such as those that live in a particular state or have a birthday this month. Likewise, the `GET /V1/invoices` endpoint can return all the recently-generated invoices. This type of functionality is not required for the frontend, so it is not available in GraphQL queries. The queries are designed to improve the customer's user experience by quickly retrieving the data needed to render pages. +The Magento REST GET endpoints retrieve a wide variety of information on behalf of the merchant. Many of these endpoints are for retrieving backend information. For example, the `GET /V1/customers/search` endpoint can be used to find a subset of customers that meet certain criteria, such as those that live in a particular state or have a birthday this month. Likewise, the `GET /V1/invoices` endpoint can return all the recently-generated invoices. This type of functionality is not required for the frontend, so it is not available in GraphQL queries. The queries are designed to improve the customer's user experience by quickly retrieving the data needed to render pages. Over time, the Magento GraphQL queries will duplicate the functionality of all storefront-facing GET calls, while making it possible to query more data in one request. The main difference will be that GraphQL will support storefront use cases, while REST will support admin use cases. @@ -35,7 +35,7 @@ query myCartQuery{ } ``` -In the preceding example, `myCartQuery` identifies your implementation of the `cart` query. `cart_id` is a non-nullable string that defines the cart to query. (The exclamation point indicates the value is non-nullable.) The `Cart` output object defines which fields to return. +In the preceding example, `myCartQuery` identifies your implementation of the `cart` query. `cart_id` is a non-nullable string that defines the cart to query. (The exclamation point indicates the value is non-nullable.) The `Cart` output object defines which fields to return. Now let's fully define a query: @@ -137,7 +137,7 @@ Variables are defined separately in JSON: Introspection queries allow you to return information about the schema. For example, you might want a list of Magento GraphQL queries or details about a specific data type. The GraphQL specification determines the structure of introspection queries. See [Introspection](https://graphql.org/learn/introspection/) for more information. -For Magento, introspection queries MUST have the operation name `IntrospectionQuery`. If you omit the operation name, or use a different name, the query returns incomplete results. +A Magento introspection query returns the same result whether or not you assign it an operation name, such as `IntrospectionQuery`. ### Example introspection queries diff --git a/src/guides/v2.3/graphql/queries/products.md b/src/guides/v2.3/graphql/queries/products.md index 002bbb3a458..05b51ba33d6 100644 --- a/src/guides/v2.3/graphql/queries/products.md +++ b/src/guides/v2.3/graphql/queries/products.md @@ -12,10 +12,10 @@ The `products` query allows you to search for catalog items. ```graphql products( search: String - filter: ProductFilterInput + filter: ProductAttributeFilterInput pageSize: Int currentPage: Int - sort: ProductSortInput + sort: ProductSortFilterInput ): Products ``` @@ -23,49 +23,129 @@ products( Each query attribute is defined below: -Attribute | Description ---- | --- -`search` | Performs a full-text search using the specified key words. This attribute is optional. See [Queries]({{ page.baseurl }}/graphql/queries/index.html) for more information. -`filter` | Identifies which attributes to search for and return. This attribute is required. See [ProductFilterInput](#ProductFilterInput) for more information. -`pageSize` | Specifies the maximum number of results to return at once. The default value is 20. See [Queries]({{ page.baseurl }}/graphql/queries/index.html) for more information. -`currentPage` | Specifies which page of results to return. The default value is 1. See [Queries]({{ page.baseurl }}/graphql/queries/index.html) for more information. -`sort` | Specifies which attribute to sort on, and whether to return the results in ascending or descending order. See [Queries]({{ page.baseurl }}/graphql/queries/index.html) for more information. -`Products` | An output object that contains the results of the query. See [Output attributes](#Response) for details. +Attribute | Data type | Description +--- | --- | --- +`search` | String | Performs a full-text search using the specified key words +`filter` | ProductAttributeFilterInput | Identifies which attributes to search for and return. See [filter attribute](#ProductFilterInput) object for more information +`pageSize` | Int | Specifies the maximum number of results to return at once. The default value is 20 +`currentPage` | Int | Specifies which page of results to return. The default value is 1 +`sort` | ProductAttributeSortInput | Specifies which attribute to sort on, and whether to return the results in ascending or descending order ### search attribute -The `search` element causes Magento to perform a full text search on the specified keywords. (This is the same type of search that is performed from the storefront.) If multiple keywords are specified, each keyword is evaluated separately. +The `search` attribute causes Magento to perform a full text search on the specified keywords. This is the same type of search that is performed from the storefront. If multiple keywords are specified, each keyword is evaluated separately. -The `search` element is optional, but it can be used with or without filters. Each query must contain a `search` or `filter` element. +Each query must contain a `search` or `filter` attribute, or both. ### filter attribute {#ProductFilterInput} -The `ProductFilterInput` object defines the filters to be used in the search. A filter contains at least one attribute, a comparison operator, and the value that is being searched for. The following example filter searches for products that has a `sku` that contains the string `24-MB` with a `price` that's less than `50`. +The `ProductAttributeFilterInput` object determines which attributes will be used to narrow the results in a `products` query. A filter contains at least one attribute, a comparison operator, and the value that is being searched for. The following example filter searches for products that have a `name` that contains the string `Bag` with a `price` that's less than or equal to `40`. ```graphql filter: { - sku: { - like: "24-MB%" + name: { + match: "Bag" } price: { - lt: "50" + to: "40" } } ``` -Search filters are logically ANDed unless an `or` statement is specified. The search query can contain unlimited number of nested `or` clauses. However, you cannot perform a logical `or` across two AND clauses, such as (A AND B) OR (X AND Y). +Magento processes the attribute values specified in a `ProductAttributeFilterInput` as simple data types (strings, integers, Booleans). However, returned attributes can be a different, complex data type. For example, in a response, `price` is an object that contains a monetary value and a currency code. + +By default, you can use the following attributes as filters. To define a custom filter, see [Filtering with custom attributes]({{page.baseurl}}/graphql/custom-filters.html). Use the `input_type` output attribute of the [`customAttributeMetadata` query]({{page.baseurl}}/graphql/queries/custom-attribute-metadata.html) to determine whether your custom filter should include the `FilterEqualTypeInput`, `FilterMatchTypeInput`, or `FilterRangeTypeInput` data type. + +Attribute | Data type | Description +--- | --- | --- +`category_id` | FilterEqualTypeInput | Filters by category ID +`description` | FilterMatchTypeInput | Filters on the Description attribute +`name` | FilterMatchTypeInput | Filters on the Product Name attribute +`price` | FilterRangeTypeInput | Filters on the Price attribute +`short_description` | FilterMatchTypeInput | Filters on the Short Description attribute +`sku` | FilterEqualTypeInput | Filters on the SKU attribute +`url_key` | FilterEqualTypeInput | The part of the URL that identifies the product + +#### FilterEqualTypeInput attributes + +The `category_id`, `sku`, and `url_key` filters require a `FilterEqualTypeInput` object as input. You must specify a `FilterEqualTypeInput` object to filter on a custom product attribute of the following types: + +- Boolean +- Select +- Multiple select + +Attribute | Data type | Description +--- | --- | --- +`eq` | String | Use this attribute to exactly match the specified string. For example, to filter on a specific category ID, specify a value like `5` +`in` | [String] | Use this attribute to filter on an array of values. For example, to filter on category IDs 4, 5, and 6, specify a value of `["4", "5", "6"]` + +#### FilterMatchTypeInput attributes + +Use the `FilterMatchTypeInput` object to construct a filter that returns products that exactly match a string or contain the specified pattern. + +Attribute | Data type | Description +--- | --- | --- +`match` | String | Use this attribute to exactly match the specified string. For example, to filter on a specific SKU, specify a value such as `24-MB01` + +You must specify a `FilterMatchTypeInput` object to filter on a custom product attribute of the following types: -Magento processes the attribute values specified in a `ProductFilterInput` as simple data types (strings, integers, booleans). However, returned attributes can be a different, complex, data type. For example, in a response, `price` is an object that contains a monetary value and a currency code. +- Text field +- Text area +- Any other type not explicitly listed in `FilterEqualTypeInput`, `FilterMatchTypeInput`, or `FilterRangeTypeInput` -The following attributes can be used to create filters. See the [Output attributes](#Response) section for information about each attribute. +#### FilterRangeTypeInput attributes + +Use the `FilterRangeTypeInput` object to construct a filter that returns products that fall within a range of prices or dates. + +Attribute | Data type | Description +--- | --- | --- +`from` | String | Use this attribute to specify the lowest possible value in the range +`to` | String | Use this attribute to specify the highest possible value in the range + +### pageSize attribute {#pageSize} + +Magento's GraphQL implementation of pagination uses offsets so that it operates in the same manner as REST and SOAP API requests. + +The `pageSize` attribute specifies the maximum number of items to return. If no value is specified, 20 items are returned. + +### currentPage attribute + +The `currentPage` attribute specifies which page of results to return. If no value is specified, the first page is returned. Magento returns an error if you specify a value that is greater than the number of available pages. + +### sort attribute + +The `sort` attribute allows you to specify which field or fields to use for sorting the results. If you specify more than one field, Magento sorts by the first field listed. Then, if any items have the same value, those items will be sorted by the secondary field. The value for each field can be set to either `ASC` or `DESC`. + +If you do not specify a `sort` object, Magento sorts as follows: + +- If you specify the `search` attribute, the query sorts by relevance, in descending order. +- If you specify the `filter` attribute without specifying the `search` attribute, the query sorts by position, in ascending order. + +In previous versions, the `sort` attribute required a `ProductSortInput` object as input. The `sort` attribute now requires a `ProductAttributeSortInput` object, which can contain the following attributes: + +Attribute | Data type | Description +--- | --- | --- +`name` | SortEnum | Sorts by Product Name +`position` | SortEnum | Sorts by the position of products +`price` | SortEnum | Sorts by Price +`relevance` | SortEnum | (Default) Sorts by the search relevance score + +{:.bs-callout-info} +If you use MySQL for searches and you specify `relevance` and another sorting attribute, the `relevance` results are always listed first. This limitation does not apply to [Elasticsearch]({{page.baseurl}}/config-guide/elasticsearch/configure-magento.html). + +## Deprecated input attributes + +The `filter` and `sort` attributes require new input objects. The following sections list the deprecated attributes. + +### ProductFilterInput attributes + +The `filter` attribute previously required a `ProductFilterInput` object as input. This object has been deprecated. The replacement input object, `ProductAttributeFilterInput` is more restrictive about what attributes can be used in a `products` query by default. The following attributes can no longer be used in default filters. See [Filtering with custom attributes]({{page.baseurl}}/graphql/custom-filters.html) for more information. ```text -category_id country_of_manufacture created_at custom_layout custom_layout_update -description gift_message_available has_options image @@ -76,15 +156,11 @@ meta_description meta_keyword meta_title min_price -name news_from_date news_to_date options_container or -price required_options -short_description -sku small_image small_image_label special_from_date @@ -100,131 +176,188 @@ url_path weight ``` -The following attributes are not used in responses: +{:.bs-callout-info} +The `or` attribute cannot be used in a `products` query. Logical OR searches are no longer supported. + +- `or` - The keyword required to perform a logical OR comparison. +- `news_from_date` - This attribute is transformed to `new_from_date` in a response. +- `news_to_date` - This attribute is transformed to `new_to_date` in a response. + +The following condition types have been deprecated: + +```text +from +gt +gteq +like +lt +lteq +moreq +neq +nin +nlike +notnull +null +to +``` + +- Comparable on Storefront +- Use in Layered Navigation +- Use in Search Results Layered Navigation +- Visible on Catalog Pages on Storefront +- Used in Product Listing +- Used for Sorting in Product Listing" + +{:.bs-callout-info} +Wildcards are no longer supported in `products` queries. + +### ProductSortInput attributes + +The following sorting attributes have been deprecated: + +```text +country_of_manufacture +created_at +custom_layout_update +custom_layout +description +gift_message_available +has_options +image_label +image +manufacturer +meta_description +meta_keyword +meta_title +news_from_date +news_to_date +options_container +required_options +short_description +sku +small_image_label +small_image +special_from_date +special_price +special_to_date +thumbnail_label +thumbnail +tier_price +updated_at +weight +``` + +## Output attributes {#Response} -* `or` - The keyword required to perform a logical OR comparison. -* `news_from_date` - This attribute is transformed to `new_from_date` in a response. -* `news_to_date` - This attribute is transformed to `new_to_date` in a response. +The query returns a `Products` object containing the following information: -{% -include note.html -type="info" -content="GraphQL automatically filters out a product attribute if ALL of the following fields are set to **No** on the attribute's Storefront Properties page in Admin: +Attribute | Data type | Description +--- | --- | --- +`aggregations` | [[Aggregation]](#Aggregation) | Layered navigation aggregations +`filters` | LayerFilter | Deprecated. Use `aggregations` instead +`items` | [[ProductInterface]](#ProductInterface) | An array of products that match the specified search criteria +`page_info` | [SearchResultPageInfo](#SearchResultPageInfo) | An object that includes the `page_info` and `currentPage` values specified in the query +`sort_fields` | [SortFields](#SortFields) | An object that includes the default sort field and all available sort fields +`total_count` | Int | The number of products returned -* Comparable on Storefront -* Use in Layered Navigation -* Use in Search Results Layered Navigation -* Visible on Catalog Pages on Storefront -* Used in Product Listing -* Used for Sorting in Product Listing" +### Aggregation attributes {#Aggregation} -%} +Each aggregation within the `aggregations` object is a separate bucket that contains the attribute code and label for each filterable option (such as price, category ID, and custom attributes). It also includes the number of products within the filterable option that match the specified search criteria. -#### Condition types and search values +Attribute | Data type | Description +--- | --- | --- +`attribute_code` | String! | Attribute code of the filter item +`count` | Int | The number of filter items in the filter group +`label` | String | The filter name displayed in layered navigation +`options` | [AggregationOption] | Describes each aggregated filter option -The following table lists available condition types and provides the SQL statement equivalents. +#### AggregationOption attributes {#AggregationOption} -Magento GraphQL clause | SQL equivalent ---- | --- -`eq: "value"` | field = 'value' -`neq: "value"` |field != 'value' -`like: "value%"` | field LIKE 'value%' -`nlike: "value%"` |field NOT LIKE 'value%' -`in: [1, 2, 3]` | field IN (1, 2, 3) -`nin: [1, 2, 3]` | field NOT IN (1, 2, 3) -`notnull: true` | field IS NOT NULL -`null: true` | field IS NULL -`lt: "value"` | field < 'value' -`gt: "value"` | field > 'value' -`gteq: "value"` | field >= 'value' -`lteq: "value"` | field <= 'value' -`moreq: "value"` | field >= 'value' -`from: "value1"` `to: "value2"` | field BETWEEN 'value1' AND 'value2' +The `AggregationOption` array contains a list of possible options for the `attribute_code` defined in the aggregation. For example, if the `attribute_code` is `category_id`, the return options could include tops, bottoms, gear, and so on. -`to` and `from` must always be used together. These condition types can be used in the same search term. For example, `quantity: {from: "10" to: "20"}`. +Attribute | Data type | Description +--- | --- | --- +`count` | Int | The number of items returned by the filter +`label` | String! | The label of the filter +`value` | String! | The internal ID representing the value of the option -`gt` and `lt` can be used in the same search term. For example, `quantity: {gt: "10" lt: "20"}`. +### ProductInterface attributes {#ProductInterface} -### pageSize attribute {#pageSize} +The `items` object contains information about each product that match the search criteria. [ProductInterface]({{page.baseurl}}/graphql/product/product-interface.html) describes the possible contents of this object. -Magento's GraphQL implementation of pagination uses offsets so that it operates in the same manner as REST and SOAP API requests. +### SearchResultPageInfo attributes {#SearchResultPageInfo} -The `pageSize` attribute specifies the maximum number of items to return. If no value is specified, 20 items are returned. +The `SearchResultPageInfo` object provides navigation for the query response. -### currentPage attribute +Attribute | Data type | Description +--- | --- | --- +`current_page` | Int | Specifies which page of results to return +`page_size` | Int | Specifies the maximum number of items to return +`total_pages` | Int | The total number of pages returned -The `currentPage` attribute specifies which page of results to return. If no value is specified, the first page is returned. Magento returns an error if you specify a value that is greater than the number of available pages. +### SortFields attributes {#SortFields} -### sort attribute +The `SortFields` object contains the default value for sort fields as well as all possible sort fields. -The `sort` object allows you to specify which field or fields to use for sorting the results. If you specify more than one field, Magento sorts by the first field listed. Then, if any items have the same value, those items will be sorted by the secondary field. The value for each field can be set to either `ASC` or `DESC`. +Attribute | Type | Description +--- | --- | --- +`default` | String | The default sort field +`options` | [SortField] | An array that contains all the fields that can be used for sorting -In the following example, Magento returns a list of items that are sorted in order of decreasing price. If two or more items have the same price, the items are listed in alphabetic order by name. +#### SortField attributes -```graphql -sort: { - price: DESC - name: ASC -} -``` +The `SortField` object contains a list of all the attributes that can be used to sort query results. -## Output attributes {#Response} +Attribute | Type | Description +--- | --- | --- +`label` | String | The label of a sortable option +`value` | String | The attribute code of the sort field -The system returns a `Products` object containing the following information: +## Deprecated output attributes -```json -items: [ProductInterface] -page_info: SearchResultPageInfo -total_count: Int -filters: [LayerFilter] -sort_fields: SortFields -``` +The `filters` output object has been deprecated in favor of the `aggregations` object. The following sections list the deprecated attributes. -Each attribute is described below: +### LayerFilter object -Attribute | Data type | Description +The `LayerFilter` object can be returned in a response to help create layered navigation on your app. + +Attribute | Type | Description --- | --- | --- -`filters` | [LayerFilter] | An array of layered navigation filters. These filters can be used to implement layered navigation on your app. -`items` | [ProductInterface] | An array of products that match the specified search criteria. [ProductInterface]({{page.baseurl}}/graphql/product/product-interface.html) describes the possible contents of this object. -`page_info` | SearchResultPageInfo | An object that includes the `page_info` and `currentPage` values specified in the query -`sort_fields` | SortFields | An object that includes the default sort field and all available sort fields -`total_count` | Int | The number of products returned +`filter_items` | [LayerFilterItemInterface] | An array of filter items +`filter_items_count` | Int | The number of filter items in filter group +`name` | String | The layered navigation filter name +`request_var` | String | The request variable name for the filter query -When a product requires a filter attribute that is not a field on its output schema, inject the attribute name into the class in a module's `di.xml` file. - -```xml - - - - field - other_field - - - -``` +### LayerFilterItemInterface -This example adds `field_to_sort` and `other_field_to_sort` attributes to the `additionalAttributes` array defined in the `ProductEntityAttributesForAst` class. The array already contains the `min_price`, `max_price`, and `category_ids` attributes. +`LayerFilterItemInterface` contains an array of items that match the terms defined in the filter. + +Attribute | Type | Description +--- | --- | --- +`items_count` | Int | The number of items the filter returned +`label` | String | The label applied to a filter +`value_string` | String | The value for filter request variable to be used in a query ## Sample queries +This section illustrates some of the many ways that you can use the `products` query. + ### Full text search The following search returns items that contain the word `yoga` or `pants`. The Catalog Search index contains search terms taken from the product `name`, `description`, `short_description` and related attributes. +**Request:** + ```graphql { - products( - search: "Yoga pants" - pageSize: 10 - ) - { + products(search: "Yoga pants", pageSize: 10) { total_count items { name sku - price { - regularPrice { - amount { + price_range { + minimum_price { + regular_price { value currency } @@ -239,45 +372,76 @@ The following search returns items that contain the word `yoga` or `pants`. The } ``` -The search returns 45 items. +**Response:** + +The search returns 45 items, but only the first two items are returned on the current page. + +```json +{ + "data": { + "products": { + "total_count": 45, + "items": [ + { + "name": "Josie Yoga Jacket", + "sku": "WJ02", + "price_range": { + "minimum_price": { + "regular_price": { + "value": 56.25, + "currency": "USD" + } + } + } + }, + { + "name": "Selene Yoga Hoodie", + "sku": "WH05", + "price_range": { + "minimum_price": { + "regular_price": { + "value": 42, + "currency": "USD" + } + } + } + } + ], + "page_info": { + "page_size": 2, + "current_page": 1 + } + } + } +} +``` -### Full text search with filters +### Full text search with filter The following sample query returns a list of products that meets the following criteria: -* The product name, product description, or related field contains the string `Messenger` (which causes it to be available for full text searches). -* The SKU begins with `24-MB` -* The price is less than $50. +- The product name, product description, or related field contains the string `Messenger` (which causes it to be available for full text searches). +- The SKU begins with `24-MB` +- The price is less than $50. -The response for each item includes the `name`, `sku`, `price` and `description` only. Up to 25 results are returned at a time, in decreasing order of price. +The response for each item includes the `name`, `sku`, and `price` only. Up to 25 results are returned at a time, in decreasing order of price. + +**Request:** ```graphql { products( search: "Messenger" - filter: { - sku: { - like: "24-MB%" - } - price: { - lt: "50" - } - } + filter: { price: { to: "50" } } pageSize: 25 - sort: { - price: DESC - } - ) - { + sort: { price: DESC } + ) { items { name sku - description { - html - } - price { - regularPrice { - amount { + price_range { + minimum_price { + regular_price { value currency } @@ -292,7 +456,7 @@ The response for each item includes the `name`, `sku`, `price` and `description` } ``` -The query returns the following: +**Response:** ```json { @@ -300,14 +464,11 @@ The query returns the following: "products": { "items": [ { - "name": "Wayfarer Messenger Bag", - "sku": "24-MB05", - "description": { - "html": "

Perfect for class, work or the gym, the Wayfarer Messenger Bag is packed with pockets. The dual-buckle flap closure reveals an organizational panel, and the roomy main compartment has spaces for your laptop and a change of clothes. An adjustable shoulder strap and easy-grip handle promise easy carrying.

\n
    \n
  • Multiple internal zip pockets.
  • \n
  • Made of durable nylon.
  • \n
" - }, - "price": { - "regularPrice": { - "amount": { + "name": "Rival Field Messenger", + "sku": "24-MB06", + "price_range": { + "minimum_price": { + "regular_price": { "value": 45, "currency": "USD" } @@ -315,14 +476,23 @@ The query returns the following: } }, { - "name": "Rival Field Messenger", - "sku": "24-MB06", - "description": { - "html": "

The Rival Field Messenger packs all your campus, studio or trail essentials inside a unique design of soft, textured leather - with loads of character to spare. Two exterior pockets keep all your smaller items handy, and the roomy interior offers even more space.

\n
    \n
  • Leather construction.
  • \n
  • Adjustable fabric carry strap.
  • \n
  • Dimensions: 18\" x 10\" x 4\".
  • \n
" - }, - "price": { - "regularPrice": { - "amount": { + "name": "Push It Messenger Bag", + "sku": "24-WB04", + "price_range": { + "minimum_price": { + "regular_price": { + "value": 45, + "currency": "USD" + } + } + } + }, + { + "name": "Wayfarer Messenger Bag", + "sku": "24-MB05", + "price_range": { + "minimum_price": { + "regular_price": { "value": 45, "currency": "USD" } @@ -330,7 +500,7 @@ The query returns the following: } } ], - "total_count": 2, + "total_count": 3, "page_info": { "page_size": 25 } @@ -339,31 +509,35 @@ The query returns the following: } ``` -### Simple search using a timestamp +### Query with layered navigation + +The following query returns aggregations for a query that filters on items with these characteristics: -The following search finds all products that were added after the specified time (midnight, November 1, 2017). +- Women's pants (category ID `27`) +- In the price range of $30 - $39.99 +- Comes in black (color `49`) + +**Request:** ```graphql { - products( - filter: { - created_at: { - gt: "2017-11-01 00:00:00" + products(filter: {category_id: {eq: "27"}, price: {from: "30", to: "39.99"}, color: {eq: "49"}}, pageSize: 25, sort: {name: DESC}) { + aggregations { + attribute_code + count + label + options { + label + value + count } } - pageSize: 25 - sort: { - price: DESC - } - ) - { - total_count items { name sku - price { - regularPrice { - amount { + price_range { + minimum_price { + regular_price { value currency } @@ -372,109 +546,486 @@ The following search finds all products that were added after the specified time } page_info { page_size - current_page } } } ``` -### Simple Logical OR search +**Response:** -The following example searches for all products whose `sku` begins with the string `24-MB` or whose `name` ends with `Bag`. +{% collapsible Show sample response %} -```graphql +```json { - products( - filter: { - or: { - sku: { - like: "24-MB%" - } - name: { - like: "%Bag" + "data": { + "products": { + "aggregations": [ + { + "attribute_code": "price", + "count": 1, + "label": "Price", + "options": [ + { + "label": "30-*", + "value": "30_*", + "count": 4 + } + ] + }, + { + "attribute_code": "category_id", + "count": 5, + "label": "Category", + "options": [ + { + "label": "New Luma Yoga Collection", + "value": "8", + "count": 1 + }, + { + "label": "Bottoms", + "value": "22", + "count": 4 + }, + { + "label": "Pants", + "value": "27", + "count": 4 + }, + { + "label": "Pants", + "value": "32", + "count": 4 + }, + { + "label": "Performance Fabrics", + "value": "35", + "count": 2 + } + ] + }, + { + "attribute_code": "color", + "count": 8, + "label": "Color", + "options": [ + { + "label": "Black", + "value": "49", + "count": 4 + }, + { + "label": "Blue", + "value": "50", + "count": 2 + }, + { + "label": "Gray", + "value": "52", + "count": 1 + }, + { + "label": "Green", + "value": "53", + "count": 1 + }, + { + "label": "Orange", + "value": "56", + "count": 1 + }, + { + "label": "Purple", + "value": "57", + "count": 1 + }, + { + "label": "Red", + "value": "58", + "count": 1 + }, + { + "label": "White", + "value": "59", + "count": 1 + } + ] + }, + { + "attribute_code": "material", + "count": 7, + "label": "Material", + "options": [ + { + "label": "Nylon", + "value": "37", + "count": 1 + }, + { + "label": "Rayon", + "value": "39", + "count": 1 + }, + { + "label": "LumaTech™", + "value": "148", + "count": 1 + }, + { + "label": "Microfiber", + "value": "150", + "count": 2 + }, + { + "label": "Spandex", + "value": "151", + "count": 2 + }, + { + "label": "Organic Cotton", + "value": "154", + "count": 2 + }, + { + "label": "CoolTech™", + "value": "156", + "count": 2 + } + ] + }, + { + "attribute_code": "size", + "count": 2, + "label": "Size", + "options": [ + { + "label": "28", + "value": "172", + "count": 4 + }, + { + "label": "29", + "value": "173", + "count": 4 + } + ] + }, + { + "attribute_code": "eco_collection", + "count": 2, + "label": "Eco Collection", + "options": [ + { + "label": "0", + "value": "0", + "count": 3 + }, + { + "label": "1", + "value": "1", + "count": 1 + } + ] + }, + { + "attribute_code": "performance_fabric", + "count": 2, + "label": "Performance Fabric", + "options": [ + { + "label": "0", + "value": "0", + "count": 2 + }, + { + "label": "1", + "value": "1", + "count": 2 + } + ] + }, + { + "attribute_code": "erin_recommends", + "count": 1, + "label": "Erin Recommends", + "options": [ + { + "label": "0", + "value": "0", + "count": 4 + } + ] + }, + { + "attribute_code": "new", + "count": 2, + "label": "New", + "options": [ + { + "label": "0", + "value": "0", + "count": 3 + }, + { + "label": "1", + "value": "1", + "count": 1 + } + ] + }, + { + "attribute_code": "sale", + "count": 1, + "label": "Sale", + "options": [ + { + "label": "0", + "value": "0", + "count": 4 + } + ] + }, + { + "attribute_code": "style_bottom", + "count": 5, + "label": "Style Bottom", + "options": [ + { + "label": "Capri", + "value": "107", + "count": 2 + }, + { + "label": "Leggings", + "value": "109", + "count": 1 + }, + { + "label": "Parachute", + "value": "110", + "count": 1 + }, + { + "label": "Sweatpants", + "value": "113", + "count": 1 + }, + { + "label": "Track Pants", + "value": "115", + "count": 1 + } + ] + }, + { + "attribute_code": "pattern", + "count": 2, + "label": "Pattern", + "options": [ + { + "label": "Color-Blocked", + "value": "195", + "count": 3 + }, + { + "label": "Solid", + "value": "197", + "count": 1 + } + ] + }, + { + "attribute_code": "climate", + "count": 5, + "label": "Climate", + "options": [ + { + "label": "Indoor", + "value": "205", + "count": 4 + }, + { + "label": "Mild", + "value": "206", + "count": 4 + }, + { + "label": "Spring", + "value": "208", + "count": 1 + }, + { + "label": "Warm", + "value": "209", + "count": 2 + }, + { + "label": "Hot", + "value": "212", + "count": 3 + } + ] } - } - } - pageSize: 25 - sort: { - price: DESC - } - ) - { - total_count - items { - name - sku - price { - regularPrice { - amount { - value - currency + ], + "items": [ + { + "name": "Karmen Yoga Pant", + "sku": "WP01", + "price_range": { + "minimum_price": { + "regular_price": { + "value": 39, + "currency": "USD" + } + } + } + }, + { + "name": "Ida Workout Parachute Pant", + "sku": "WP03", + "price_range": { + "minimum_price": { + "regular_price": { + "value": 48, + "currency": "USD" + } + } + } + }, + { + "name": "Bardot Capri", + "sku": "WP08", + "price_range": { + "minimum_price": { + "regular_price": { + "value": 48, + "currency": "USD" + } + } + } + }, + { + "name": "Aeon Capri", + "sku": "WP07", + "price_range": { + "minimum_price": { + "regular_price": { + "value": 48, + "currency": "USD" + } + } } } + ], + "page_info": { + "page_size": 25 } } - page_info { - page_size - current_page - } } } ``` -The query returns 8 items. +{% endcollapsible %} + +### Return minimum and maximum prices and discount information -### Logical AND and OR search +In the following example, a catalog price rule that provides a 10% discount on all fitness equipment is in effect. The product queried, `24-WG080`, is the Sprite Yoga Companion Kit bundle product. This product has two user-selected options that cause the price to vary. If you choose to query a product that is not a composite (bundle, group, or configurable) product, the minimum and maximum prices are the same. -This query searches for products that have `name` that ends with `Short` or has a `sku` that indicates the product is a pair of women’s pants (`WP%`). The system performs a logical AND to restrict the results to those that cost from $40 to $49.99. +**Request:** ```graphql { - products( - filter: { - price: { - from: "40" to: "49.99" - } - or: { - name: { - like: "%Short" - } - sku: { - like: "WP%" - } - } - } - pageSize: 25 - sort: { - price: DESC - } - ) - { - total_count + products(filter: {sku: {eq: "24-WG080"}}, sort: {name: ASC}) { items { name sku - price { - regularPrice { - amount { + price_range { + minimum_price { + regular_price { value + currency + } + final_price { + value + currency + } + discount { + amount_off + percent_off + } + } + maximum_price { + regular_price { + value + currency + } + final_price { + value + currency + } + discount { + amount_off + percent_off } } } } - page_info { - page_size - current_page + } +} +``` + +**Response:** + +```json +{ + "data": { + "products": { + "items": [ + { + "name": "Sprite Yoga Companion Kit", + "sku": "24-WG080", + "price_range": { + "minimum_price": { + "regular_price": { + "value": 61, + "currency": "USD" + }, + "final_price": { + "value": 61, + "currency": "USD" + }, + "discount": { + "amount_off": 0, + "percent_off": 0 + } + }, + "maximum_price": { + "regular_price": { + "value": 77, + "currency": "USD" + }, + "final_price": { + "value": 77, + "currency": "USD" + }, + "discount": { + "amount_off": 0, + "percent_off": 0 + } + } + } + } + ] } } } ``` -The query returns 14 items. +### Retrieve related products, up-sells, and cross-sells -### Retrieve related products, Up-sells and Cross-sells +The following query shows how to get related products, up-sells, and cross-sells for a product: -The following query shows how to get related products, Up-sells and Cross-sells for the particular product: +**Request:** ```graphql { @@ -573,35 +1124,6 @@ The following query shows how to get related products, Up-sells and Cross-sells } ``` -### Layered navigation - -The following query returns layered navigation for products that have a `sku` containing the string `24-WB`. - -```graphql -{ - products( - filter: { sku: { like: "24-WB%" } } - pageSize: 20 - currentPage: 1 - sort: { name: DESC } - ) { - items { - sku - } - filters { - name - filter_items_count - request_var - filter_items { - label - value_string - items_count - } - } - } -} -``` - ### Media gallery search The following query returns media gallery information about the product with the `sku` of `24-MB01`. @@ -681,55 +1203,6 @@ query { } ``` -### Include website information with `products` query results {#inclWebsiteInfoExample} - -The [ProductInterface]({{ page.baseurl }}/graphql/product/product-interface.html) can include information about the `Website` object. - -**Request:** - -```graphql -{ - products(filter: {sku: {eq: "24-WB04"}}) - { - items{ - websites { - id - name - code - sort_order - default_group_id - is_default - } - } - } -} -``` - -**Response:** - -```json -{ - "data": { - "products": { - "items": [ - { - "websites": [ - { - "id": 1, - "name": "Main Website", - "code": "base", - "sort_order": 0, - "default_group_id": "1", - "is_default": true - } - ] - } - ] - } - } -} -``` - ### Query a URL's rewrite information {#urlRewriteExample} The following product query returns URL rewrite information about the Joust Duffle Bag. diff --git a/src/guides/v2.3/graphql/queries/store-config.md b/src/guides/v2.3/graphql/queries/store-config.md index 211124622fe..a2f1b25127a 100644 --- a/src/guides/v2.3/graphql/queries/store-config.md +++ b/src/guides/v2.3/graphql/queries/store-config.md @@ -38,6 +38,7 @@ The following call returns all details of a store's configuration. secure_base_link_url secure_base_static_url secure_base_media_url + store_name } } ``` @@ -63,7 +64,8 @@ The following call returns all details of a store's configuration. "secure_base_url": "http://magento2.vagrant193/", "secure_base_link_url": "http://magento2.vagrant193/", "secure_base_static_url": "http://magento2.vagrant193/pub/static/version1536249714/", - "secure_base_media_url": "http://magento2.vagrant193/pub/media/" + "secure_base_media_url": "http://magento2.vagrant193/pub/media/", + "store_name": "My Store" } } } @@ -177,6 +179,36 @@ The following query returns information about the store's catalog configuration. } ``` +### Query a store's fixed product tax configuration + +The following query returns enumeration values that indicate the store's fixed product tax configuration. + +**Request:** + +```graphql +{ + storeConfig { + category_fixed_product_tax_display_setting + product_fixed_product_tax_display_setting + sales_fixed_product_tax_display_setting + } +} +``` + +**Response:** + +```json +{ + "data": { + "storeConfig": { + "category_fixed_product_tax_display_setting": "EXCLUDE_FPT_WITHOUT_DETAILS", + "product_fixed_product_tax_display_setting": "EXCLUDE_FPT_AND_INCLUDE_WITH_DETAILS", + "sales_fixed_product_tax_display_setting": "INCLUDE_FPT_WITHOUT_DETAILS" + } + } +} +``` + ## Output attributes ### Supported storeConfig attributes @@ -198,6 +230,7 @@ Attribute | Data Type | Description | Example `secure_base_media_url` | String | The secure fully-qualified URL that specifies the location of user media files | `https://magentohost.example.com/pub/media/` `secure_base_static_url` | String | The secure fully-qualified URL that specifies the location of static view files | `https://magentohost.example.com/pub/static/` `secure_base_url` | String | The store's fully-qualified secure base URL | `https://magentohost.example.com/` +`store_name` | String | The store's name | `My Store` `timezone` | String | The store's time zone | `America/Chicago` `website_id` | Integer | The ID number assigned to the parent website | `1` `weight_unit` | String | The weight unit for products | `lbs`, `kgs`, etc @@ -245,14 +278,35 @@ Attribute | Data Type | Description | Example --- | --- | --- `catalog_default_sort_by` | String | The default sort order of the search results list | `position` `category_url_suffix` | String | The suffix applied to category pages, such as `.htm` or `.html` | `.html` -`grid_per_page` | Integer | The default number of products per page in Grid View | `9` -`grid_per_page_values` | String | A list of numbers that define how many products can be displayed in List View | `9,15,30` +`grid_per_page` | Int | The default number of products per page in Grid View | `9` +`grid_per_page_values` | A list of numbers that define how many products can be displayed in List View | `9,15,30` `list_mode` | String | The format of the search results list | `grid-list` -`list_per_page` | Integer | The default number of products per page in List View | `10` +`list_per_page` | Int | The default number of products per page in List View | `10` `list_per_page_values` | String | A list of numbers that define how many products can be displayed in List View | `5,10,15,20,25` `product_url_suffix` | String | The suffix applied to product pages, such as `.htm` or `.html` | `.html` +`root_category_id` | Int | The ID of the root category `title_separator` | String | Identifies the character that separates the category name and subcategory in the browser title bar | `-` +### Supported WEEE (fixed product tax) attributes + +The **Stores** > Settings > **Configuration** > **Sales** > **Tax** > **Fixed Product Taxes** panel contains several fields that determine how to display fixed product tax (FPT) values and descriptions. Use the following attributes to determine the values of the **Fixed Product Taxes** fields. These attributes are defined in the `WeeeGraphQl` module. + +Attribute | Data Type | Description +--- | --- | --- +`category_fixed_product_tax_display_setting` | FixedProductTaxDisplaySettings | Corresponds to the **Display Prices In Product Lists** field. It indicates how FPT information is displayed on category pages +`product_fixed_product_tax_display_setting` | FixedProductTaxDisplaySettings | Corresponds to the **Display Prices On Product View Page** field. It indicates how FPT information is displayed on product pages +`sales_fixed_product_tax_display_setting` | FixedProductTaxDisplaySettings | Corresponds to the **Display Prices In Sales Modules** field. It indicates how FPT information is displayed on cart, checkout, and order pages + +The `FixedProductTaxDisplaySettings` data type is an enumeration that describes whether displayed prices include fixed product taxes and whether Magento separately displays detailed information about the FPTs. + +Value | Description +--- | --- +EXCLUDE_FPT_AND_INCLUDE_WITH_DETAILS | The displayed price does not include the FPT amount. You must display the values of `ProductPrice.fixed_product_taxes` and the price including the FPT separately. This value corresponds to **Excluding FPT, Including FPT description and final price** +EXCLUDE_FPT_WITHOUT_DETAILS | The displayed price does not include the FPT amount. The values from `ProductPrice.fixed_product_taxes` are not displayed. This value corresponds to **Excluding FPT** +FPT_DISABLED | The FPT feature is not enabled. You can omit `ProductPrice.fixed_product_taxes` from your query +INCLUDE_FPT_WITH_DETAILS | The displayed price includes the FPT amount while displaying the values of `ProductPrice.fixed_product_taxes` separately. This value corresponds to **Including FPT and FPT description** +INCLUDE_FPT_WITHOUT_DETAILS | The displayed price includes the FPT amount without displaying the `ProductPrice.fixed_product_taxes` values. This value corresponds to **Including FPT only** + ## Extend configuration data You can add your own configuration to the `storeConfig` query within your own module. diff --git a/src/guides/v2.3/graphql/queries/url-resolver.md b/src/guides/v2.3/graphql/queries/url-resolver.md index d033b5a32f0..317bac1274f 100644 --- a/src/guides/v2.3/graphql/queries/url-resolver.md +++ b/src/guides/v2.3/graphql/queries/url-resolver.md @@ -51,7 +51,7 @@ The `urlResolver` query contains the following attribute. Attribute | Type | Description --- | --- | --- -`url` | String | The requested URL +`url` | String | The requested URL. To query for product and category pages, the `url` value must contain the URL key and suffix. For CMS page queries, the `url` value must contain the URL key only. ## Output attributes diff --git a/src/guides/v2.3/graphql/queries/wishlist.md b/src/guides/v2.3/graphql/queries/wishlist.md index b9f35e038c8..27d3bb70c7a 100644 --- a/src/guides/v2.3/graphql/queries/wishlist.md +++ b/src/guides/v2.3/graphql/queries/wishlist.md @@ -5,6 +5,9 @@ redirect_from: - /guides/v2.3/graphql/reference/wishlist.html --- +{:.bs-callout-warning} +The `wishlist` query has been deprecated. Wish list information is now provided by the [customer]({{page.baseurl}}/graphql/queries/customer.html) query. + Use the `wishlist` query to retrieve information about a customer's wish list. [Get customer authorization token]({{page.baseurl}}/graphql/get-customer-authorization-token.html) describes how to supply an authorization token for a specific customer. ## Syntax diff --git a/src/guides/v2.3/graphql/tutorials/checkout/checkout-billing-address.md b/src/guides/v2.3/graphql/tutorials/checkout/checkout-billing-address.md index 6ea9bb15f00..c9c6115d6a2 100644 --- a/src/guides/v2.3/graphql/tutorials/checkout/checkout-billing-address.md +++ b/src/guides/v2.3/graphql/tutorials/checkout/checkout-billing-address.md @@ -103,7 +103,7 @@ mutation { ## Add a new address for billing and shipping -The following mutation includes the `use_for_shipping` attribute, which allows the same address to be used for billing and shipping. +The following mutation includes the `same_as_shipping` attribute, which allows the same address to be used for billing and shipping. **Request:** @@ -125,7 +125,7 @@ mutation { telephone: "123-456-0000" save_in_address_book: false } - use_for_shipping: true + same_as_shipping: true } } ) { diff --git a/src/guides/v2.3/graphql/tutorials/checkout/checkout-payment-method.md b/src/guides/v2.3/graphql/tutorials/checkout/checkout-payment-method.md index 4f46b3069b6..b41f1dd6cd3 100644 --- a/src/guides/v2.3/graphql/tutorials/checkout/checkout-payment-method.md +++ b/src/guides/v2.3/graphql/tutorials/checkout/checkout-payment-method.md @@ -58,8 +58,8 @@ There are two mutation queries in GraphQl which can be use to set the payment me |Mutation|Description| |--- |--- | -|`setPaymentMethodOnCart`|Sets the payment method for your order| -|`setPaymentMethodAndPlaceOrder`|Sets the payment method and then immediately places your order. In this case ["Step 10. Place the order"]({{ page.baseurl }}/graphql/tutorials/checkout/checkout-place-order.html) can be skipped| +|`setPaymentMethodOnCart`|Sets the payment method for your order.| +|`setPaymentMethodAndPlaceOrder`| **Deprecated** Sets the payment method and then immediately places your order. In this case ["Step 10. Place the order"]({{ page.baseurl }}/graphql/tutorials/checkout/checkout-place-order.html) can be skipped.| ### Set payment method on cart {#setPaymentMethodOnCart} @@ -70,7 +70,7 @@ Use the `setPaymentMethodOnCart` mutation to set the payment method for your ord {:.bs-callout-info} For logged-in customers, send the customer's authorization token in the `Authorization` parameter of the header. See ["Get customer authorization token"]({{ page.baseurl }}/graphql/get-customer-authorization-token.html) for more information. -```text +```graphql mutation { setPaymentMethodOnCart(input: { cart_id: "{ CART_ID }" @@ -109,9 +109,12 @@ If the operation is successful, the response contains the code of the selected p Use the `setPaymentMethodAndPlaceOrder` mutation to set the payment method and place the order. +{:.bs-callout-warning} +The `setPaymentMethodAndPlaceOrder` mutation has been deprecated. + **Request:** -```text +```graphql mutation { setPaymentMethodAndPlaceOrder(input: { cart_id: "{ CART_ID }" diff --git a/src/guides/v2.3/graphql/tutorials/checkout/checkout-place-order.md b/src/guides/v2.3/graphql/tutorials/checkout/checkout-place-order.md index d844d4f71e1..d08b1e739b6 100644 --- a/src/guides/v2.3/graphql/tutorials/checkout/checkout-place-order.md +++ b/src/guides/v2.3/graphql/tutorials/checkout/checkout-place-order.md @@ -27,7 +27,7 @@ For logged-in customers, send the customer's authorization token in the `Authori mutation { placeOrder(input: {cart_id: "{ CART_ID }"}) { order { - order_id + order_number } } } @@ -40,7 +40,7 @@ mutation { "data": { "placeOrder": { "order": { - "order_id": "000000001" + "order_number": "000000001" } } } diff --git a/src/guides/v2.3/install-gde/install/cli/install-cli-install.md b/src/guides/v2.3/install-gde/install/cli/install-cli-install.md index a8498211048..357129fbce1 100644 --- a/src/guides/v2.3/install-gde/install/cli/install-cli-install.md +++ b/src/guides/v2.3/install-gde/install/cli/install-cli-install.md @@ -68,7 +68,7 @@ magento setup:install --